View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang.math;
18  
19  import java.io.Serializable;
20  
21  /**
22   * <p><code>IntRange</code> represents an inclusive range of <code>int</code>s.</p>
23   *
24   * @author Stephen Colebourne
25   * @since 2.0
26   * @version $Id: IntRange.java 594398 2007-11-13 02:43:10Z bayard $
27   */
28  public final class IntRange extends Range implements Serializable {
29      
30      /**
31       * Required for serialization support.
32       * 
33       * @see java.io.Serializable
34       */
35      private static final long serialVersionUID = 71849363892730L;
36  
37      /**
38       * The minimum number in this range (inclusive).
39       */
40      private final int min;
41      /**
42       * The maximum number in this range (inclusive).
43       */
44      private final int max;
45      
46      /**
47       * Cached output minObject (class is immutable).
48       */
49      private transient Integer minObject = null;
50      /**
51       * Cached output maxObject (class is immutable).
52       */
53      private transient Integer maxObject = null;
54      /**
55       * Cached output hashCode (class is immutable).
56       */
57      private transient int hashCode = 0;
58      /**
59       * Cached output toString (class is immutable).
60       */
61      private transient String toString = null;
62      
63      /**
64       * <p>Constructs a new <code>IntRange</code> using the specified
65       * number as both the minimum and maximum in this range.</p>
66       *
67       * @param number  the number to use for this range
68       */
69      public IntRange(int number) {
70          super();
71          this.min = number;
72          this.max = number;
73      }
74  
75      /**
76       * <p>Constructs a new <code>IntRange</code> using the specified
77       * number as both the minimum and maximum in this range.</p>
78       *
79       * @param number  the number to use for this range, must not be <code>null</code>
80       * @throws IllegalArgumentException if the number is <code>null</code>
81       */
82      public IntRange(Number number) {
83          super();
84          if (number == null) {
85              throw new IllegalArgumentException("The number must not be null");
86          }
87          this.min = number.intValue();
88          this.max = number.intValue();
89          if (number instanceof Integer) {
90              this.minObject = (Integer) number;
91              this.maxObject = (Integer) number;
92          }
93      }
94  
95      /**
96       * <p>Constructs a new <code>IntRange</code> with the specified
97       * minimum and maximum numbers (both inclusive).</p>
98       * 
99       * <p>The arguments may be passed in the order (min,max) or (max,min). The
100      * getMinimum and getMaximum methods will return the correct values.</p>
101      * 
102      * @param number1  first number that defines the edge of the range, inclusive
103      * @param number2  second number that defines the edge of the range, inclusive
104      */
105     public IntRange(int number1, int number2) {
106         super();
107         if (number2 < number1) {
108             this.min = number2;
109             this.max = number1;
110         } else {
111             this.min = number1;
112             this.max = number2;
113         }
114     }
115 
116     /**
117      * <p>Constructs a new <code>IntRange</code> with the specified
118      * minimum and maximum numbers (both inclusive).</p>
119      * 
120      * <p>The arguments may be passed in the order (min,max) or (max,min). The
121      * getMinimum and getMaximum methods will return the correct values.</p>
122      *
123      * @param number1  first number that defines the edge of the range, inclusive
124      * @param number2  second number that defines the edge of the range, inclusive
125      * @throws IllegalArgumentException if either number is <code>null</code>
126      */
127     public IntRange(Number number1, Number number2) {
128         super();
129         if (number1 == null || number2 == null) {
130             throw new IllegalArgumentException("The numbers must not be null");
131         }
132         int number1val = number1.intValue();
133         int number2val = number2.intValue();
134         if (number2val < number1val) {
135             this.min = number2val;
136             this.max = number1val;
137             if (number2 instanceof Integer) {
138                 this.minObject = (Integer) number2;
139             }
140             if (number1 instanceof Integer) {
141                 this.maxObject = (Integer) number1;
142             }
143         } else {
144             this.min = number1val;
145             this.max = number2val;
146             if (number1 instanceof Integer) {
147                 this.minObject = (Integer) number1;
148             }
149             if (number2 instanceof Integer) {
150                 this.maxObject = (Integer) number2;
151             }
152         }
153     }
154 
155     // Accessors
156     //--------------------------------------------------------------------
157 
158     /**
159      * <p>Returns the minimum number in this range.</p>
160      *
161      * @return the minimum number in this range
162      */
163     public Number getMinimumNumber() {
164         if (minObject == null) {
165             minObject = new Integer(min);            
166         }
167         return minObject;
168     }
169 
170     /**
171      * <p>Gets the minimum number in this range as a <code>long</code>.</p>
172      *
173      * @return the minimum number in this range
174      */
175     public long getMinimumLong() {
176         return min;
177     }
178 
179     /**
180      * <p>Gets the minimum number in this range as a <code>int</code>.</p>
181      *
182      * @return the minimum number in this range
183      */
184     public int getMinimumInteger() {
185         return min;
186     }
187 
188     /**
189      * <p>Gets the minimum number in this range as a <code>double</code>.</p>
190      *
191      * @return the minimum number in this range
192      */
193     public double getMinimumDouble() {
194         return min;
195     }
196 
197     /**
198      * <p>Gets the minimum number in this range as a <code>float</code>.</p>
199      *
200      * @return the minimum number in this range
201      */
202     public float getMinimumFloat() {
203         return min;
204     }
205 
206     /**
207      * <p>Returns the maximum number in this range.</p>
208      *
209      * @return the maximum number in this range
210      */
211     public Number getMaximumNumber() {
212         if (maxObject == null) {
213             maxObject = new Integer(max);            
214         }
215         return maxObject;
216     }
217 
218     /**
219      * <p>Gets the maximum number in this range as a <code>long</code>.</p>
220      *
221      * @return the maximum number in this range
222      */
223     public long getMaximumLong() {
224         return max;
225     }
226 
227     /**
228      * <p>Gets the maximum number in this range as a <code>int</code>.</p>
229      *
230      * @return the maximum number in this range
231      */
232     public int getMaximumInteger() {
233         return max;
234     }
235 
236     /**
237      * <p>Gets the maximum number in this range as a <code>double</code>.</p>
238      *
239      * @return the maximum number in this range
240      */
241     public double getMaximumDouble() {
242         return max;
243     }
244 
245     /**
246      * <p>Gets the maximum number in this range as a <code>float</code>.</p>
247      *
248      * @return the maximum number in this range
249      */
250     public float getMaximumFloat() {
251         return max;
252     }
253 
254     // Tests
255     //--------------------------------------------------------------------
256     
257     /**
258      * <p>Tests whether the specified <code>number</code> occurs within
259      * this range using <code>int</code> comparison.</p>
260      * 
261      * <p><code>null</code> is handled and returns <code>false</code>.</p>
262      *
263      * @param number  the number to test, may be <code>null</code>
264      * @return <code>true</code> if the specified number occurs within this range
265      */
266     public boolean containsNumber(Number number) {
267         if (number == null) {
268             return false;
269         }
270         return containsInteger(number.intValue());
271     }
272 
273     /**
274      * <p>Tests whether the specified <code>int</code> occurs within
275      * this range using <code>int</code> comparison.</p>
276      * 
277      * <p>This implementation overrides the superclass for performance as it is
278      * the most common case.</p>
279      * 
280      * @param value  the int to test
281      * @return <code>true</code> if the specified number occurs within this
282      *  range by <code>int</code> comparison
283      */
284     public boolean containsInteger(int value) {
285         return value >= min && value <= max;
286     }
287 
288     // Range tests
289     //--------------------------------------------------------------------
290 
291     /**
292      * <p>Tests whether the specified range occurs entirely within this range
293      * using <code>int</code> comparison.</p>
294      * 
295      * <p><code>null</code> is handled and returns <code>false</code>.</p>
296      *
297      * @param range  the range to test, may be <code>null</code>
298      * @return <code>true</code> if the specified range occurs entirely within this range
299      * @throws IllegalArgumentException if the range is not of this type
300      */
301     public boolean containsRange(Range range) {
302         if (range == null) {
303             return false;
304         }
305         return containsInteger(range.getMinimumInteger()) &&
306                containsInteger(range.getMaximumInteger());
307     }
308 
309     /**
310      * <p>Tests whether the specified range overlaps with this range
311      * using <code>int</code> comparison.</p>
312      * 
313      * <p><code>null</code> is handled and returns <code>false</code>.</p>
314      *
315      * @param range  the range to test, may be <code>null</code>
316      * @return <code>true</code> if the specified range overlaps with this range
317      */
318     public boolean overlapsRange(Range range) {
319         if (range == null) {
320             return false;
321         }
322         return range.containsInteger(min) ||
323                range.containsInteger(max) || 
324                containsInteger(range.getMinimumInteger());
325     }
326 
327     // Basics
328     //--------------------------------------------------------------------
329 
330     /**
331      * <p>Compares this range to another object to test if they are equal.</p>.
332      * 
333      * <p>To be equal, the class, minimum and maximum must be equal.</p>
334      *
335      * @param obj the reference object with which to compare
336      * @return <code>true</code> if this object is equal
337      */
338     public boolean equals(Object obj) {
339         if (obj == this) {
340             return true;
341         }
342         if (obj instanceof IntRange == false) {
343             return false;
344         }
345         IntRange range = (IntRange) obj;
346         return min == range.min && max == range.max;
347     }
348 
349     /**
350      * <p>Gets a hashCode for the range.</p>
351      *
352      * @return a hash code value for this object
353      */
354     public int hashCode() {
355         if (hashCode == 0) {
356             hashCode = 17;
357             hashCode = 37 * hashCode + getClass().hashCode();
358             hashCode = 37 * hashCode + min;
359             hashCode = 37 * hashCode + max;
360         }
361         return hashCode;
362     }
363 
364     /**
365      * <p>Gets the range as a <code>String</code>.</p>
366      *
367      * <p>The format of the String is 'Range[<i>min</i>,<i>max</i>]'.</p>
368      *
369      * @return the <code>String</code> representation of this range
370      */
371     public String toString() {
372         if (toString == null) {
373             StringBuffer buf = new StringBuffer(32);
374             buf.append("Range[");
375             buf.append(min);
376             buf.append(',');
377             buf.append(max);
378             buf.append(']');
379             toString = buf.toString();
380         }
381         return toString;
382     }
383 
384     /**
385      * <p>Returns an array containing all the integer values in the range.</p>
386      *
387      * @return the <code>int[]</code> representation of this range
388      * @since 2.4
389      */
390     public int[] toArray() {
391         int[] array = new int[max - min + 1];
392         for (int i = 0; i < array.length; i++) {
393             array[i] = min + i;
394         }
395 
396         return array;
397     }
398 }