KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > bak > pcj > set > LongRange


1 /*
2  * Primitive Collections for Java.
3  * Copyright (C) 2002 Søren Bak
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19 package bak.pcj.set;
20
21 import bak.pcj.util.Exceptions;
22 import java.io.Serializable JavaDoc;
23
24 /**
25  * This class represents ranges of consecutive long values.
26  *
27  * <p>Design note: Empty ranges cannot exist. It gives too many
28  * problems defining adjacency and intersections, and empty ranges
29  * are not really useful for their purpose of backing up range sets.
30  * It also removes the problem of overflow checking.
31  *
32  * @author S&oslash;ren Bak
33  * @version 1.3 21-08-2003 20:10
34  * @since 1.0
35  */

36 public class LongRange implements Comparable JavaDoc, Serializable JavaDoc {
37
38     /**
39      * The first value in this range.
40      * @serial
41      */

42     private long first;
43
44     /**
45      * The last value in this range.
46      * @serial
47      */

48     private long last;
49
50     /**
51      * Creates a new range of consecutive long values.
52      *
53      * @param first
54      * the first long value in the range.
55      *
56      * @param last
57      * the last long value in the range.
58      *
59      * @throws IllegalArgumentException
60      * if <tt>first &gt; last</tt>.
61      */

62     public LongRange(long first, long last) {
63         if (last < first)
64             Exceptions.invalidRangeBounds(String.valueOf(first), String.valueOf(last));
65         this.first = first;
66         this.last = last;
67     }
68
69     /*
70      * Creates a new range of consecutive long values.
71      *
72      * @param first
73      * the first long value in the range.
74      *
75      * @param length
76      * the number of consecutive values in the new
77      * range.
78      *
79      * @throws IllegalArgumentException
80      * if <tt>length &lt;= 0</tt>;
81      * if the specified length results in an overflow,
82      * i.e. there are values not in the defined range of
83      * long values.
84      */

85     /*
86     public LongRange(long first, int length) {
87         if (length <= 0)
88             throw new IllegalArgumentException();
89         // first+length-1 > MAX_VALUE rewritten to avoid overflow
90         if (first-1 > Long.MAX_VALUE-length)
91             throw new IllegalArgumentException();
92         this.first = first;
93         this.last = (long)(first+length-1);
94     }
95     */

96
97     /**
98      * Returns the first long value in this range.
99      *
100      * @return the first long value in this range.
101      */

102     public long first()
103     { return first; }
104
105     /**
106      * Returns the last long value in this range.
107      *
108      * @return the last long value in this range.
109      */

110     public long last()
111     { return last; }
112
113     /**
114      * Returns the number of values in this range.
115      *
116      * @return the number of values in this range.
117      */

118     public int length() {
119         return (int)(last-first+1);
120     }
121
122     /**
123      * Indicates whether this range intersects a specified range.
124      *
125      * @param range
126      * the range with which to compare this range.
127      *
128      * @return <tt>true</tt> if this range has at least one
129      * value in common with the specified range.
130      *
131      * @throws NullPointerException
132      * if <tt>range</tt> is <tt>null</tt>.
133      */

134     public boolean intersects(LongRange range) {
135         return (first >= range.first && first <= range.last)
136             || (range.first >= first && range.first <= last);
137     }
138
139     /**
140      * Indicates whether this range is adjacent to a specified
141      * range.
142      *
143      * @param range
144      * the range with which to compare this range.
145      *
146      * @return <tt>true</tt> if this range is adjacent to the
147      * specified range.
148      *
149      * @throws NullPointerException
150      * if <tt>range</tt> is <tt>null</tt>.
151      */

152     public boolean adjacentTo(LongRange range) {
153         return (last+1 == range.first)
154             || (range.last+1 == first);
155     }
156
157     /**
158      * Indicates whether this can be merged with a specified range.
159      * Two ranges can be merged if a range of consecutive values
160      * containing all values of both ranges exists.
161      *
162      * @param range
163      * the range to merge with.
164      *
165      * @return <tt>true</tt> if this range can be merged with
166      * the specified range; returns <tt>false</tt>
167      * otherwise.
168      *
169      * @throws NullPointerException
170      * if <tt>range</tt> is <tt>null</tt>.
171      */

172     public boolean canMergeWith(LongRange range) {
173         return intersects(range) || adjacentTo(range);
174     }
175
176     /**
177      * Creates a new range as a merge between this range and a
178      * specified range.
179      *
180      * @param range
181      * the range with which to merge this range.
182      *
183      * @throws NullPointerException
184      * if <tt>range</tt> is <tt>null</tt>.
185      *
186      * @throws IllegalArgumentException
187      * if this range cannot be merged with the specified
188      * range.
189      */

190     public LongRange mergeWith(LongRange range) {
191         if (!canMergeWith(range))
192             Exceptions.cannotMergeRanges(this, range);
193         return quickMergeWith(range);
194     }
195
196     private LongRange quickMergeWith(LongRange range) {
197         long nfirst = first < range.first ? first : range.first;
198         long nlast = last > range.last ? last : range.last;
199         return new LongRange(nfirst, nlast);
200     }
201
202     public LongRange tryMergeWith(LongRange range) {
203         if (!canMergeWith(range))
204             return null;
205         return quickMergeWith(range);
206     }
207
208     /**
209      * Returns the length of the intersection between this
210      * range and a specified range.
211      *
212      * @param range
213      * the range with which to intersect this rance.
214      *
215      * @return the length of the intersection between this
216      * range and a specified range.
217      *
218      * @throws NullPointerException
219      * if <tt>range</tt> is <tt>null</tt>.
220      */

221     public int intersectionLength(LongRange range) {
222         int len;
223         if (first >= range.first && first <= range.last) {
224             long end = last <= range.last ? last : range.last;
225             len = ((int)(end-first))+1;
226         } else
227             if (range.first >= first && range.first <= last) {
228                 long end = last <= range.last ? last : range.last;
229                 len = ((int)(end-range.first))+1;
230             } else
231                 len = 0;
232         return len;
233     }
234     
235
236     /**
237      * Indicates whether a specified value is a member of this
238      * range.
239      *
240      * @param v
241      * the value to test for membership.
242      *
243      * @return <tt>true</tt> if the specified value is a member
244      * of this range; returns <tt>false</tt> otherwise.
245      */

246     public boolean contains(long v) {
247         return v >= first && v <= last;
248     }
249
250     /**
251      * Indicates whether this range is equal to some object.
252      *
253      * @param obj
254      * the object with which to compare this range.
255      *
256      * @return <tt>true</tt> if this range is equal to the
257      * specified object; returns <tt>false</tt>
258      * otherwise.
259      */

260     public boolean equals(Object JavaDoc obj) {
261         if (!(obj instanceof LongRange))
262             return false;
263         LongRange range = (LongRange)obj;
264         return first == range.first && last == range.last;
265     }
266
267     /**
268      * Compares this range with some object for order.
269      *
270      * @param obj
271      * the object with which to compare this range.
272      *
273      * @return <tt>-1</tt> if this range is less than
274      * <tt>obj</tt>; returns <tt>1</tt> if this range is
275      * greater than <tt>obj</tt>; returns <tt>0</tt>
276      * otherwise, in which case <tt>this.equals(obj)</tt>
277      * is <tt>true</tt>.
278      *
279      * @throws NullPointerException
280      * if <tt>obj</tt> is <tt>null</tt>.
281      *
282      * @throws ClassCastException
283      * if <tt>obj</tt> is not of class <tt>LongRange</tt>.
284      */

285     public int compareTo(Object JavaDoc obj) {
286         LongRange range = (LongRange)obj;
287         if (first < range.first)
288             return -1;
289         if (first > range.first)
290             return 1;
291         if (last < range.last)
292             return -1;
293         if (last > range.last)
294             return 1;
295         return 0;
296     }
297
298     /**
299      * Returns a hash code value for this range.
300      *
301      * @return a hash code value for this range.
302      */

303     public int hashCode() {
304         return (int)(first ^ last);
305     }
306
307     /**
308      * Returns a string representation of this range.
309      *
310      * @return a string representation of this range.
311      */

312     public String JavaDoc toString() {
313         return bak.pcj.util.Display.display(first) + "-" + bak.pcj.util.Display.display(last);
314     }
315
316 }
Popular Tags