| 1 | |
|
| 2 | |
|
| 3 | |
|
| 4 | |
|
| 5 | |
|
| 6 | |
package jaggregate; |
| 7 | |
|
| 8 | |
import java.io.Serializable; |
| 9 | |
import java.util.NoSuchElementException; |
| 10 | |
|
| 11 | |
import jaggregate.internal.Casting; |
| 12 | |
import jaggregate.internal.ReadOnlySequences; |
| 13 | |
import jaggregate.internal.number.OperableNumber; |
| 14 | |
import static jaggregate.OrderedCollection.*; |
| 15 | |
import static jaggregate.internal.ArgumentChecks.*; |
| 16 | |
import static jaggregate.internal.Casting.*; |
| 17 | |
import static jaggregate.internal.number.OperableNumberFactory.*; |
| 18 | |
|
| 19 | |
|
| 20 | |
|
| 21 | |
|
| 22 | |
|
| 23 | |
|
| 24 | |
|
| 25 | |
|
| 26 | |
|
| 27 | |
|
| 28 | |
|
| 29 | |
|
| 30 | |
|
| 31 | |
|
| 32 | |
|
| 33 | |
|
| 34 | |
|
| 35 | |
|
| 36 | 8325 | public class Interval<E extends Number> extends AbstractCollection<E> |
| 37 | |
implements ReadOnlySequence<E>, Serializable { |
| 38 | |
|
| 39 | |
private static final long serialVersionUID = -1L; |
| 40 | |
|
| 41 | |
private final OperableNumber<E> begin; |
| 42 | |
private final OperableNumber<E> end; |
| 43 | |
private final OperableNumber<E> step; |
| 44 | |
private final int size; |
| 45 | |
|
| 46 | |
|
| 47 | |
|
| 48 | |
|
| 49 | |
|
| 50 | |
|
| 51 | |
|
| 52 | |
|
| 53 | |
|
| 54 | |
|
| 55 | |
|
| 56 | |
|
| 57 | |
public Interval( E from, E to ) { |
| 58 | 1466 | this( from, to, null ); |
| 59 | 1466 | } |
| 60 | |
|
| 61 | |
|
| 62 | |
|
| 63 | |
|
| 64 | |
|
| 65 | |
|
| 66 | |
|
| 67 | |
|
| 68 | |
|
| 69 | |
|
| 70 | |
|
| 71 | |
|
| 72 | |
|
| 73 | |
|
| 74 | |
|
| 75 | |
|
| 76 | |
|
| 77 | |
|
| 78 | |
|
| 79 | |
|
| 80 | |
|
| 81 | |
|
| 82 | |
|
| 83 | 5876 | public Interval( E from, E to, E by ) { |
| 84 | 5876 | ensureNotNull( from, "lower bound" ); |
| 85 | 5876 | ensureNotNull( to, "upper bound" ); |
| 86 | |
|
| 87 | 5876 | OperableNumber<E> opFrom = cast( wrap( from ) ); |
| 88 | 5876 | OperableNumber<E> opTo = cast( wrap( to ) ); |
| 89 | 5876 | OperableNumber<E> opBy = by == null |
| 90 | |
? opTo.one() |
| 91 | |
: Casting.<OperableNumber<E>>cast( wrap( by ) ); |
| 92 | |
|
| 93 | 5876 | if ( opBy.isZero() ) |
| 94 | 8 | throw new IllegalArgumentException( "zero step" ); |
| 95 | |
|
| 96 | 5868 | begin = opFrom; |
| 97 | 5868 | if ( isEmptyIntervalSpecified( opFrom, opTo, opBy ) ) |
| 98 | 769 | end = opTo; |
| 99 | |
else |
| 100 | 5099 | end = opTo.minus( from ).dividedBy( opBy ).times( opBy ).plus( opFrom ); |
| 101 | |
|
| 102 | 5868 | step = opBy; |
| 103 | 5868 | size = computeSize(); |
| 104 | 5868 | } |
| 105 | |
|
| 106 | |
|
| 107 | |
|
| 108 | |
|
| 109 | |
|
| 110 | |
|
| 111 | |
|
| 112 | |
|
| 113 | |
|
| 114 | |
|
| 115 | |
|
| 116 | |
|
| 117 | |
|
| 118 | |
|
| 119 | |
public static <T extends Number> Interval<T> fromTo( T from, T to ) { |
| 120 | 1466 | return new Interval<T>( from, to ); |
| 121 | |
} |
| 122 | |
|
| 123 | |
|
| 124 | |
|
| 125 | |
|
| 126 | |
|
| 127 | |
|
| 128 | |
|
| 129 | |
|
| 130 | |
|
| 131 | |
|
| 132 | |
|
| 133 | |
|
| 134 | |
|
| 135 | |
|
| 136 | |
|
| 137 | |
|
| 138 | |
|
| 139 | |
|
| 140 | |
|
| 141 | |
|
| 142 | |
|
| 143 | |
|
| 144 | |
|
| 145 | |
|
| 146 | |
public static <T extends Number> Interval<T> fromToBy( T from, T to, T by ) { |
| 147 | 4410 | return new Interval<T>( from, to, by ); |
| 148 | |
} |
| 149 | |
|
| 150 | |
|
| 151 | |
|
| 152 | |
|
| 153 | |
@Override |
| 154 | |
public <R> ReadOnlySequence<R> collect( |
| 155 | |
UnaryFunctor<? super E, ? extends R> transformer ) { |
| 156 | |
|
| 157 | 80 | return (ReadOnlySequence<R>) super.collect( transformer ); |
| 158 | |
} |
| 159 | |
|
| 160 | |
|
| 161 | |
|
| 162 | |
|
| 163 | |
@Override |
| 164 | |
public ReadOnlySequence<E> reject( UnaryCondition<? super E> discriminator ) { |
| 165 | 88 | return (ReadOnlySequence<E>) super.reject( discriminator ); |
| 166 | |
} |
| 167 | |
|
| 168 | |
|
| 169 | |
|
| 170 | |
|
| 171 | |
@Override |
| 172 | |
public ReadOnlySequence<E> select( UnaryCondition<? super E> discriminator ) { |
| 173 | 88 | return (ReadOnlySequence<E>) super.select( discriminator ); |
| 174 | |
} |
| 175 | |
|
| 176 | |
|
| 177 | |
|
| 178 | |
|
| 179 | |
public ReadOnlySequence<E> concat( ReadOnlySequence<? extends E> otherSequence ) { |
| 180 | 40 | return ReadOnlySequences.concat( this, otherSequence ); |
| 181 | |
} |
| 182 | |
|
| 183 | |
|
| 184 | |
|
| 185 | |
|
| 186 | |
public E after( E target ) { |
| 187 | 224 | if ( !includes( target ) ) |
| 188 | 24 | throw new NoSuchElementException(); |
| 189 | |
|
| 190 | 200 | if ( step.isPositive() ) { |
| 191 | 104 | if ( begin.greaterThan( target ) || end.lessThanOrEqualTo( target ) ) |
| 192 | 32 | throw new NoSuchElementException(); |
| 193 | |
} |
| 194 | |
else { |
| 195 | 96 | if ( begin.lessThan( target ) || end.greaterThanOrEqualTo( target ) ) |
| 196 | 24 | throw new NoSuchElementException(); |
| 197 | |
} |
| 198 | |
|
| 199 | 144 | return step.plus( target ).unwrapped(); |
| 200 | |
} |
| 201 | |
|
| 202 | |
|
| 203 | |
|
| 204 | |
|
| 205 | |
public E at( int index ) { |
| 206 | 8301 | OperableNumber<E> result = step.times( index ).plus( begin ); |
| 207 | |
|
| 208 | 8301 | if ( step.isPositive() ) { |
| 209 | 5037 | if ( begin.greaterThan( result ) || end.lessThan( result ) ) |
| 210 | 56 | throw new IndexOutOfBoundsException(); |
| 211 | |
} |
| 212 | |
else { |
| 213 | 3264 | if ( begin.lessThan( result ) || end.greaterThan( result ) ) |
| 214 | 40 | throw new IndexOutOfBoundsException(); |
| 215 | |
} |
| 216 | |
|
| 217 | 8205 | return result.unwrapped(); |
| 218 | |
} |
| 219 | |
|
| 220 | |
|
| 221 | |
|
| 222 | |
|
| 223 | |
public E before( E target ) { |
| 224 | 224 | if ( !includes( target ) ) |
| 225 | 24 | throw new NoSuchElementException(); |
| 226 | |
|
| 227 | 200 | if ( step.isPositive() ) { |
| 228 | 104 | if ( begin.greaterThanOrEqualTo( target ) || end.lessThan( target ) ) |
| 229 | 32 | throw new NoSuchElementException(); |
| 230 | |
} |
| 231 | |
else { |
| 232 | 96 | if ( begin.lessThanOrEqualTo( target ) || end.greaterThan( target ) ) |
| 233 | 24 | throw new NoSuchElementException(); |
| 234 | |
} |
| 235 | |
|
| 236 | 144 | return step.negated().plus( target ).unwrapped(); |
| 237 | |
} |
| 238 | |
|
| 239 | |
|
| 240 | |
|
| 241 | |
|
| 242 | |
public ReadOnlySequence<E> copyRange( int start, int stop ) { |
| 243 | 736 | return ReadOnlySequences.copyRange( this, start, stop ); |
| 244 | |
} |
| 245 | |
|
| 246 | |
|
| 247 | |
|
| 248 | |
|
| 249 | |
public ReadOnlySequence<E> copyWith( E newElement ) { |
| 250 | 56 | return ReadOnlySequences.copyWith( this, newElement ); |
| 251 | |
} |
| 252 | |
|
| 253 | |
|
| 254 | |
|
| 255 | |
|
| 256 | |
public ReadOnlySequence<E> copyWithout( E oldElement ) { |
| 257 | 280 | return ReadOnlySequences.copyWithout( this, oldElement ); |
| 258 | |
} |
| 259 | |
|
| 260 | |
|
| 261 | |
|
| 262 | |
|
| 263 | |
public int findFirst( UnaryCondition<? super E> discriminator ) { |
| 264 | 88 | return ReadOnlySequences.findFirst( this, discriminator ); |
| 265 | |
} |
| 266 | |
|
| 267 | |
|
| 268 | |
|
| 269 | |
|
| 270 | |
public int findLast( UnaryCondition<? super E> discriminator ) { |
| 271 | 136 | return ReadOnlySequences.findLast( this, discriminator ); |
| 272 | |
} |
| 273 | |
|
| 274 | |
|
| 275 | |
|
| 276 | |
|
| 277 | |
public void forEachInReverseDo( UnaryFunctor<? super E, ?> operation ) { |
| 278 | 216 | ReadOnlySequences.forEachInReverseDo( this, operation ); |
| 279 | 104 | } |
| 280 | |
|
| 281 | |
|
| 282 | |
|
| 283 | |
|
| 284 | |
public E first() { |
| 285 | 88 | if ( isEmpty() ) |
| 286 | 24 | throw new NoSuchElementException(); |
| 287 | |
|
| 288 | 64 | return begin.unwrapped(); |
| 289 | |
} |
| 290 | |
|
| 291 | |
|
| 292 | |
|
| 293 | |
|
| 294 | |
public void forEachInRangeDo( int start, int stop, |
| 295 | |
UnaryFunctor<? super E, ?> operation ) { |
| 296 | |
|
| 297 | 776 | ReadOnlySequences.forEachInRangeDo( this, start, stop, operation ); |
| 298 | 672 | } |
| 299 | |
|
| 300 | |
|
| 301 | |
|
| 302 | |
|
| 303 | |
public void forEachInRangeDoWithIndex( int start, int stop, |
| 304 | |
BinaryFunctor<? super Integer, ? super E, ?> operation ) { |
| 305 | |
|
| 306 | 776 | ReadOnlySequences.forEachInRangeDoWithIndex( this, start, stop, operation ); |
| 307 | 672 | } |
| 308 | |
|
| 309 | |
|
| 310 | |
|
| 311 | |
|
| 312 | |
public int indexOf( E target ) { |
| 313 | 272 | return ReadOnlySequences.indexOf( this, target ); |
| 314 | |
} |
| 315 | |
|
| 316 | |
|
| 317 | |
|
| 318 | |
|
| 319 | |
public int indexOf( ReadOnlySequence<? extends E> targetSequence, int start ) { |
| 320 | 40 | return ReadOnlySequences.indexOf( this, targetSequence, start ); |
| 321 | |
} |
| 322 | |
|
| 323 | |
|
| 324 | |
|
| 325 | |
|
| 326 | |
public void doWithIndex( BinaryFunctor<? super Integer, ? super E, ?> operation ) { |
| 327 | 970 | ReadOnlySequences.doWithIndex( this, operation ); |
| 328 | 706 | } |
| 329 | |
|
| 330 | |
|
| 331 | |
|
| 332 | |
|
| 333 | |
public E last() { |
| 334 | 80 | if ( isEmpty() ) |
| 335 | 24 | throw new NoSuchElementException(); |
| 336 | |
|
| 337 | 56 | return end.unwrapped(); |
| 338 | |
} |
| 339 | |
|
| 340 | |
|
| 341 | |
|
| 342 | |
|
| 343 | |
public ReadOnlySequence<E> reverse() { |
| 344 | 80 | return ReadOnlySequences.reverse( this ); |
| 345 | |
} |
| 346 | |
|
| 347 | |
|
| 348 | |
|
| 349 | |
|
| 350 | |
@Override |
| 351 | |
public boolean equals( Object that ) { |
| 352 | 657 | return ReadOnlySequences.areSequencesEqual( this, that ); |
| 353 | |
} |
| 354 | |
|
| 355 | |
|
| 356 | |
|
| 357 | |
|
| 358 | |
@Override |
| 359 | |
public int hashCode() { |
| 360 | 90 | return ReadOnlySequences.hashCode( this ); |
| 361 | |
} |
| 362 | |
|
| 363 | |
|
| 364 | |
|
| 365 | |
|
| 366 | |
@Override |
| 367 | |
public String toString() { |
| 368 | 3 | return ReadOnlySequences.toString( this ); |
| 369 | |
} |
| 370 | |
|
| 371 | |
|
| 372 | |
|
| 373 | |
|
| 374 | |
public <T> void doWithOthers( ReadOnlySequence<? extends T> otherSequence, |
| 375 | |
BinaryFunctor<? super E, ? super T, ?> operation ) { |
| 376 | |
|
| 377 | 104 | ReadOnlySequences.doWithOthers( this, otherSequence, operation ); |
| 378 | 80 | } |
| 379 | |
|
| 380 | |
|
| 381 | |
|
| 382 | |
|
| 383 | |
public void forEachDo( UnaryFunctor<? super E, ?> operation ) { |
| 384 | 1434 | if ( step.isPositive() ) |
| 385 | 882 | forEachDoPositiveStep( operation ); |
| 386 | |
else |
| 387 | 552 | forEachDoNegativeStep( operation ); |
| 388 | 1290 | } |
| 389 | |
|
| 390 | |
private void forEachDoPositiveStep( UnaryFunctor<? super E, ?> operation ) { |
| 391 | 882 | for ( OperableNumber<E> i = cast( wrap( begin.unwrapped() ) ); |
| 392 | 3640 | i.lessThanOrEqualTo( end ); |
| 393 | 2758 | i.incrementBy( step ) ) { |
| 394 | |
|
| 395 | 2846 | operation.evaluate( i.unwrapped() ); |
| 396 | |
} |
| 397 | 794 | } |
| 398 | |
|
| 399 | |
private void forEachDoNegativeStep( UnaryFunctor<? super E, ?> operation ) { |
| 400 | 552 | for ( OperableNumber<E> i = cast( wrap( begin.unwrapped() ) ); |
| 401 | 2880 | i.greaterThanOrEqualTo( end ); |
| 402 | 2328 | i.incrementBy( step ) ) { |
| 403 | |
|
| 404 | 2384 | operation.evaluate( i.unwrapped() ); |
| 405 | |
} |
| 406 | 496 | } |
| 407 | |
|
| 408 | |
|
| 409 | |
|
| 410 | |
|
| 411 | |
@Override |
| 412 | |
public boolean includes( E target ) { |
| 413 | 720 | if ( target == null ) |
| 414 | 0 | return false; |
| 415 | |
|
| 416 | 720 | boolean belowMinimumPositive = |
| 417 | |
step.isPositive() && begin.greaterThan( target ); |
| 418 | 720 | boolean belowMinimumNegative = |
| 419 | |
step.isNegative() && end.greaterThan( target ); |
| 420 | |
|
| 421 | 720 | if ( belowMinimumPositive || belowMinimumNegative ) |
| 422 | 88 | return false; |
| 423 | |
|
| 424 | 632 | return begin.negated().plus( target ).modulo( step ).isZero(); |
| 425 | |
} |
| 426 | |
|
| 427 | |
|
| 428 | |
|
| 429 | |
|
| 430 | |
public int size() { |
| 431 | 7231 | return size; |
| 432 | |
} |
| 433 | |
|
| 434 | |
|
| 435 | |
|
| 436 | |
|
| 437 | |
@Override |
| 438 | |
protected ExtensibleCollection<E> newEmptyExtensibleCollection() { |
| 439 | 160 | return newEmptyExtensibleResultCollection(); |
| 440 | |
} |
| 441 | |
|
| 442 | |
|
| 443 | |
|
| 444 | |
|
| 445 | |
@Override |
| 446 | |
protected <R> ExtensibleCollection<R> newEmptyExtensibleResultCollection() { |
| 447 | 232 | return emptyOrderedCollection(); |
| 448 | |
} |
| 449 | |
|
| 450 | |
private boolean isEmptyIntervalSpecified( OperableNumber<E> from, |
| 451 | |
OperableNumber<E> to, OperableNumber<E> by ) { |
| 452 | |
|
| 453 | 5868 | boolean emptyDescending = from.lessThan( to ) && by.isNegative(); |
| 454 | 5868 | boolean emptyAscending = from.greaterThan( to ) && by.isPositive(); |
| 455 | |
|
| 456 | 5868 | return emptyDescending || emptyAscending; |
| 457 | |
} |
| 458 | |
|
| 459 | |
private int computeSize() { |
| 460 | 5868 | if ( step.isPositive() && begin.greaterThan( end ) ) |
| 461 | 513 | return 0; |
| 462 | |
|
| 463 | 5355 | if ( step.isNegative() && begin.lessThan( end ) ) |
| 464 | 256 | return 0; |
| 465 | |
|
| 466 | 5099 | return end.minus( begin ).dividedBy( step ).plus( 1 ).unwrapped().intValue(); |
| 467 | |
} |
| 468 | |
} |