001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.lang.math; 018 019 import java.io.Serializable; 020 021 /** 022 * <p><code>IntRange</code> represents an inclusive range of <code>int</code>s.</p> 023 * 024 * @author Apache Software Foundation 025 * @since 2.0 026 * @version $Id: IntRange.java 905636 2010-02-02 14:03:32Z niallp $ 027 */ 028 public final class IntRange extends Range implements Serializable { 029 030 /** 031 * Required for serialization support. 032 * 033 * @see java.io.Serializable 034 */ 035 private static final long serialVersionUID = 71849363892730L; 036 037 /** 038 * The minimum number in this range (inclusive). 039 */ 040 private final int min; 041 /** 042 * The maximum number in this range (inclusive). 043 */ 044 private final int max; 045 046 /** 047 * Cached output minObject (class is immutable). 048 */ 049 private transient Integer minObject = null; 050 /** 051 * Cached output maxObject (class is immutable). 052 */ 053 private transient Integer maxObject = null; 054 /** 055 * Cached output hashCode (class is immutable). 056 */ 057 private transient int hashCode = 0; 058 /** 059 * Cached output toString (class is immutable). 060 */ 061 private transient String toString = null; 062 063 /** 064 * <p>Constructs a new <code>IntRange</code> using the specified 065 * number as both the minimum and maximum in this range.</p> 066 * 067 * @param number the number to use for this range 068 */ 069 public IntRange(int number) { 070 super(); 071 this.min = number; 072 this.max = number; 073 } 074 075 /** 076 * <p>Constructs a new <code>IntRange</code> using the specified 077 * number as both the minimum and maximum in this range.</p> 078 * 079 * @param number the number to use for this range, must not be <code>null</code> 080 * @throws IllegalArgumentException if the number is <code>null</code> 081 */ 082 public IntRange(Number number) { 083 super(); 084 if (number == null) { 085 throw new IllegalArgumentException("The number must not be null"); 086 } 087 this.min = number.intValue(); 088 this.max = number.intValue(); 089 if (number instanceof Integer) { 090 this.minObject = (Integer) number; 091 this.maxObject = (Integer) number; 092 } 093 } 094 095 /** 096 * <p>Constructs a new <code>IntRange</code> with the specified 097 * minimum and maximum numbers (both inclusive).</p> 098 * 099 * <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 }