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