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 import org.apache.commons.lang.text.StrBuilder; 022 023 /** 024 * <p><code>IntRange</code> represents an inclusive range of <code>int</code>s.</p> 025 * 026 * @author Apache Software Foundation 027 * @since 2.0 028 * @version $Id: IntRange.java 1057072 2011-01-10 01:55:57Z niallp $ 029 */ 030 public final class IntRange extends Range implements Serializable { 031 032 /** 033 * Required for serialization support. 034 * 035 * @see java.io.Serializable 036 */ 037 private static final long serialVersionUID = 71849363892730L; 038 039 /** 040 * The minimum number in this range (inclusive). 041 */ 042 private final int min; 043 /** 044 * The maximum number in this range (inclusive). 045 */ 046 private final int max; 047 048 /** 049 * Cached output minObject (class is immutable). 050 */ 051 private transient Integer minObject = null; 052 /** 053 * Cached output maxObject (class is immutable). 054 */ 055 private transient Integer maxObject = null; 056 /** 057 * Cached output hashCode (class is immutable). 058 */ 059 private transient int hashCode = 0; 060 /** 061 * Cached output toString (class is immutable). 062 */ 063 private transient String toString = null; 064 065 /** 066 * <p>Constructs a new <code>IntRange</code> using the specified 067 * number as both the minimum and maximum in this range.</p> 068 * 069 * @param number the number to use for this range 070 */ 071 public IntRange(int number) { 072 super(); 073 this.min = number; 074 this.max = number; 075 } 076 077 /** 078 * <p>Constructs a new <code>IntRange</code> using the specified 079 * number as both the minimum and maximum in this range.</p> 080 * 081 * @param number the number to use for this range, must not be <code>null</code> 082 * @throws IllegalArgumentException if the number is <code>null</code> 083 */ 084 public IntRange(Number number) { 085 super(); 086 if (number == null) { 087 throw new IllegalArgumentException("The number must not be null"); 088 } 089 this.min = number.intValue(); 090 this.max = number.intValue(); 091 if (number instanceof Integer) { 092 this.minObject = (Integer) number; 093 this.maxObject = (Integer) number; 094 } 095 } 096 097 /** 098 * <p>Constructs a new <code>IntRange</code> with the specified 099 * minimum and maximum numbers (both inclusive).</p> 100 * 101 * <p>The arguments may be passed in the order (min,max) or (max,min). The 102 * getMinimum and getMaximum methods will return the correct values.</p> 103 * 104 * @param number1 first number that defines the edge of the range, inclusive 105 * @param number2 second number that defines the edge of the range, inclusive 106 */ 107 public IntRange(int number1, int number2) { 108 super(); 109 if (number2 < number1) { 110 this.min = number2; 111 this.max = number1; 112 } else { 113 this.min = number1; 114 this.max = number2; 115 } 116 } 117 118 /** 119 * <p>Constructs a new <code>IntRange</code> with the specified 120 * minimum and maximum numbers (both inclusive).</p> 121 * 122 * <p>The arguments may be passed in the order (min,max) or (max,min). The 123 * getMinimum and getMaximum methods will return the correct values.</p> 124 * 125 * @param number1 first number that defines the edge of the range, inclusive 126 * @param number2 second number that defines the edge of the range, inclusive 127 * @throws IllegalArgumentException if either number is <code>null</code> 128 */ 129 public IntRange(Number number1, Number number2) { 130 super(); 131 if (number1 == null || number2 == null) { 132 throw new IllegalArgumentException("The numbers must not be null"); 133 } 134 int number1val = number1.intValue(); 135 int number2val = number2.intValue(); 136 if (number2val < number1val) { 137 this.min = number2val; 138 this.max = number1val; 139 if (number2 instanceof Integer) { 140 this.minObject = (Integer) number2; 141 } 142 if (number1 instanceof Integer) { 143 this.maxObject = (Integer) number1; 144 } 145 } else { 146 this.min = number1val; 147 this.max = number2val; 148 if (number1 instanceof Integer) { 149 this.minObject = (Integer) number1; 150 } 151 if (number2 instanceof Integer) { 152 this.maxObject = (Integer) number2; 153 } 154 } 155 } 156 157 // Accessors 158 //-------------------------------------------------------------------- 159 160 /** 161 * <p>Returns the minimum number in this range.</p> 162 * 163 * @return the minimum number in this range 164 */ 165 public Number getMinimumNumber() { 166 if (minObject == null) { 167 minObject = new Integer(min); 168 } 169 return minObject; 170 } 171 172 /** 173 * <p>Gets the minimum number in this range as a <code>long</code>.</p> 174 * 175 * @return the minimum number in this range 176 */ 177 public long getMinimumLong() { 178 return min; 179 } 180 181 /** 182 * <p>Gets the minimum number in this range as a <code>int</code>.</p> 183 * 184 * @return the minimum number in this range 185 */ 186 public int getMinimumInteger() { 187 return min; 188 } 189 190 /** 191 * <p>Gets the minimum number in this range as a <code>double</code>.</p> 192 * 193 * @return the minimum number in this range 194 */ 195 public double getMinimumDouble() { 196 return min; 197 } 198 199 /** 200 * <p>Gets the minimum number in this range as a <code>float</code>.</p> 201 * 202 * @return the minimum number in this range 203 */ 204 public float getMinimumFloat() { 205 return min; 206 } 207 208 /** 209 * <p>Returns the maximum number in this range.</p> 210 * 211 * @return the maximum number in this range 212 */ 213 public Number getMaximumNumber() { 214 if (maxObject == null) { 215 maxObject = new Integer(max); 216 } 217 return maxObject; 218 } 219 220 /** 221 * <p>Gets the maximum number in this range as a <code>long</code>.</p> 222 * 223 * @return the maximum number in this range 224 */ 225 public long getMaximumLong() { 226 return max; 227 } 228 229 /** 230 * <p>Gets the maximum number in this range as a <code>int</code>.</p> 231 * 232 * @return the maximum number in this range 233 */ 234 public int getMaximumInteger() { 235 return max; 236 } 237 238 /** 239 * <p>Gets the maximum number in this range as a <code>double</code>.</p> 240 * 241 * @return the maximum number in this range 242 */ 243 public double getMaximumDouble() { 244 return max; 245 } 246 247 /** 248 * <p>Gets the maximum number in this range as a <code>float</code>.</p> 249 * 250 * @return the maximum number in this range 251 */ 252 public float getMaximumFloat() { 253 return max; 254 } 255 256 // Tests 257 //-------------------------------------------------------------------- 258 259 /** 260 * <p>Tests whether the specified <code>number</code> occurs within 261 * this range using <code>int</code> comparison.</p> 262 * 263 * <p><code>null</code> is handled and returns <code>false</code>.</p> 264 * 265 * @param number the number to test, may be <code>null</code> 266 * @return <code>true</code> if the specified number occurs within this range 267 */ 268 public boolean containsNumber(Number number) { 269 if (number == null) { 270 return false; 271 } 272 return containsInteger(number.intValue()); 273 } 274 275 /** 276 * <p>Tests whether the specified <code>int</code> occurs within 277 * this range using <code>int</code> comparison.</p> 278 * 279 * <p>This implementation overrides the superclass for performance as it is 280 * the most common case.</p> 281 * 282 * @param value the int to test 283 * @return <code>true</code> if the specified number occurs within this 284 * range by <code>int</code> comparison 285 */ 286 public boolean containsInteger(int value) { 287 return value >= min && value <= max; 288 } 289 290 // Range tests 291 //-------------------------------------------------------------------- 292 293 /** 294 * <p>Tests whether the specified range occurs entirely within this range 295 * using <code>int</code> comparison.</p> 296 * 297 * <p><code>null</code> is handled and returns <code>false</code>.</p> 298 * 299 * @param range the range to test, may be <code>null</code> 300 * @return <code>true</code> if the specified range occurs entirely within this range 301 * @throws IllegalArgumentException if the range is not of this type 302 */ 303 public boolean containsRange(Range range) { 304 if (range == null) { 305 return false; 306 } 307 return containsInteger(range.getMinimumInteger()) && 308 containsInteger(range.getMaximumInteger()); 309 } 310 311 /** 312 * <p>Tests whether the specified range overlaps with this range 313 * using <code>int</code> comparison.</p> 314 * 315 * <p><code>null</code> is handled and returns <code>false</code>.</p> 316 * 317 * @param range the range to test, may be <code>null</code> 318 * @return <code>true</code> if the specified range overlaps with this range 319 */ 320 public boolean overlapsRange(Range range) { 321 if (range == null) { 322 return false; 323 } 324 return range.containsInteger(min) || 325 range.containsInteger(max) || 326 containsInteger(range.getMinimumInteger()); 327 } 328 329 // Basics 330 //-------------------------------------------------------------------- 331 332 /** 333 * <p>Compares this range to another object to test if they are equal.</p>. 334 * 335 * <p>To be equal, the class, minimum and maximum must be equal.</p> 336 * 337 * @param obj the reference object with which to compare 338 * @return <code>true</code> if this object is equal 339 */ 340 public boolean equals(Object obj) { 341 if (obj == this) { 342 return true; 343 } 344 if (obj instanceof IntRange == false) { 345 return false; 346 } 347 IntRange range = (IntRange) obj; 348 return min == range.min && max == range.max; 349 } 350 351 /** 352 * <p>Gets a hashCode for the range.</p> 353 * 354 * @return a hash code value for this object 355 */ 356 public int hashCode() { 357 if (hashCode == 0) { 358 hashCode = 17; 359 hashCode = 37 * hashCode + getClass().hashCode(); 360 hashCode = 37 * hashCode + min; 361 hashCode = 37 * hashCode + max; 362 } 363 return hashCode; 364 } 365 366 /** 367 * <p>Gets the range as a <code>String</code>.</p> 368 * 369 * <p>The format of the String is 'Range[<i>min</i>,<i>max</i>]'.</p> 370 * 371 * @return the <code>String</code> representation of this range 372 */ 373 public String toString() { 374 if (toString == null) { 375 StrBuilder buf = new StrBuilder(32); 376 buf.append("Range["); 377 buf.append(min); 378 buf.append(','); 379 buf.append(max); 380 buf.append(']'); 381 toString = buf.toString(); 382 } 383 return toString; 384 } 385 386 /** 387 * <p>Returns an array containing all the integer values in the range.</p> 388 * 389 * @return the <code>int[]</code> representation of this range 390 * @since 2.4 391 */ 392 public int[] toArray() { 393 int[] array = new int[max - min + 1]; 394 for (int i = 0; i < array.length; i++) { 395 array[i] = min + i; 396 } 397 398 return array; 399 } 400 }