17
17
18
18
import java .util .Comparator ;
19
19
import java .util .Optional ;
20
+ import java .util .function .Function ;
20
21
21
22
import org .springframework .util .Assert ;
22
23
import org .springframework .util .ObjectUtils ;
30
31
*/
31
32
public final class Range <T > {
32
33
33
- private final static Range <?> UNBOUNDED = Range .of (Bound .unbounded (), Bound .UNBOUNDED );
34
+ private final static Range <?> UNBOUNDED = Range .of (Bound .unbounded (), Bound .unbounded () );
34
35
35
36
/**
36
37
* The lower bound of the range.
@@ -217,6 +218,22 @@ public boolean contains(T value, Comparator<T> comparator) {
217
218
return greaterThanLowerBound && lessThanUpperBound ;
218
219
}
219
220
221
+ /**
222
+ * Apply a mapping {@link Function} to the lower and upper boundary values.
223
+ *
224
+ * @param mapper must not be {@literal null}. If the mapper returns {@code null}, then the corresponding boundary
225
+ * value represents an {@link Bound#unbounded()} boundary.
226
+ * @return a new {@link Range} after applying the value to the mapper.
227
+ * @param <R>
228
+ * @since 3.0
229
+ */
230
+ public <R > Range <R > map (Function <? super T , ? extends R > mapper ) {
231
+
232
+ Assert .notNull (mapper , "Mapping function must not be null" );
233
+
234
+ return Range .of (lowerBound .map (mapper ), upperBound .map (mapper ));
235
+ }
236
+
220
237
@ Override
221
238
public String toString () {
222
239
return String .format ("%s-%s" , lowerBound .toPrefixString (), upperBound .toSuffixString ());
@@ -265,8 +282,7 @@ public int hashCode() {
265
282
*/
266
283
public static final class Bound <T > {
267
284
268
- @ SuppressWarnings ({ "rawtypes" , "unchecked" }) //
269
- private static final Bound <?> UNBOUNDED = new Bound (Optional .empty (), true );
285
+ private static final Bound <?> UNBOUNDED = new Bound <>(Optional .empty (), true );
270
286
271
287
private final Optional <T > value ;
272
288
private final boolean inclusive ;
@@ -302,7 +318,7 @@ public boolean isBounded() {
302
318
public static <T > Bound <T > inclusive (T value ) {
303
319
304
320
Assert .notNull (value , "Value must not be null" );
305
- return new Bound <> (Optional .of (value ), true );
321
+ return Bound . of (Optional .of (value ), true );
306
322
}
307
323
308
324
/**
@@ -354,7 +370,7 @@ public static Bound<Double> inclusive(double value) {
354
370
public static <T > Bound <T > exclusive (T value ) {
355
371
356
372
Assert .notNull (value , "Value must not be null" );
357
- return new Bound <> (Optional .of (value ), false );
373
+ return Bound . of (Optional .of (value ), false );
358
374
}
359
375
360
376
/**
@@ -437,6 +453,10 @@ public boolean equals(Object o) {
437
453
return false ;
438
454
}
439
455
456
+ if (!value .isPresent () && !bound .value .isPresent ()) {
457
+ return true ;
458
+ }
459
+
440
460
if (inclusive != bound .inclusive )
441
461
return false ;
442
462
@@ -445,10 +465,41 @@ public boolean equals(Object o) {
445
465
446
466
@ Override
447
467
public int hashCode () {
468
+
469
+ if (!value .isPresent ()) {
470
+ return ObjectUtils .nullSafeHashCode (value );
471
+ }
472
+
448
473
int result = ObjectUtils .nullSafeHashCode (value );
449
474
result = 31 * result + (inclusive ? 1 : 0 );
450
475
return result ;
451
476
}
477
+
478
+ /**
479
+ * Apply a mapping {@link Function} to the boundary value.
480
+ *
481
+ * @param mapper must not be {@literal null}. If the mapper returns {@code null}, then the boundary value
482
+ * corresponds with {@link Bound#unbounded()}.
483
+ * @return a new {@link Bound} after applying the value to the mapper.
484
+ * @param <R>
485
+ * @since 3.0
486
+ */
487
+ public <R > Bound <R > map (Function <? super T , ? extends R > mapper ) {
488
+
489
+ Assert .notNull (mapper , "Mapping function must not be null" );
490
+
491
+ return Bound .of (value .map (mapper ), inclusive );
492
+ }
493
+
494
+ private static <R > Bound <R > of (Optional <R > value , boolean inclusive ) {
495
+
496
+ if (value .isPresent ()) {
497
+ return new Bound <>(value , inclusive );
498
+ }
499
+
500
+ return unbounded ();
501
+ }
502
+
452
503
}
453
504
454
505
/**
0 commit comments