1515 */
1616package org .springframework .data .domain ;
1717
18+ import java .util .Comparator ;
1819import java .util .Optional ;
1920
2021import org .springframework .util .Assert ;
2728 * @author Mark Paluch
2829 * @since 1.10
2930 */
30- public final class Range <T extends Comparable < T > > {
31+ public final class Range <T > {
3132
3233 private final static Range <?> UNBOUNDED = Range .of (Bound .unbounded (), Bound .UNBOUNDED );
3334
@@ -57,7 +58,7 @@ private Range(Bound<T> lowerBound, Bound<T> upperBound) {
5758 * @since 2.0
5859 */
5960 @ SuppressWarnings ("unchecked" )
60- public static <T extends Comparable < T > > Range <T > unbounded () {
61+ public static <T > Range <T > unbounded () {
6162 return (Range <T >) UNBOUNDED ;
6263 }
6364
@@ -70,7 +71,7 @@ public static <T extends Comparable<T>> Range<T> unbounded() {
7071 * @return
7172 * @since 2.2
7273 */
73- public static <T extends Comparable < T > > Range <T > closed (T from , T to ) {
74+ public static <T > Range <T > closed (T from , T to ) {
7475 return new Range <>(Bound .inclusive (from ), Bound .inclusive (to ));
7576 }
7677
@@ -83,7 +84,7 @@ public static <T extends Comparable<T>> Range<T> closed(T from, T to) {
8384 * @return
8485 * @since 2.2
8586 */
86- public static <T extends Comparable < T > > Range <T > open (T from , T to ) {
87+ public static <T > Range <T > open (T from , T to ) {
8788 return new Range <>(Bound .exclusive (from ), Bound .exclusive (to ));
8889 }
8990
@@ -96,7 +97,7 @@ public static <T extends Comparable<T>> Range<T> open(T from, T to) {
9697 * @return
9798 * @since 2.2
9899 */
99- public static <T extends Comparable < T > > Range <T > leftOpen (T from , T to ) {
100+ public static <T > Range <T > leftOpen (T from , T to ) {
100101 return new Range <>(Bound .exclusive (from ), Bound .inclusive (to ));
101102 }
102103
@@ -109,7 +110,7 @@ public static <T extends Comparable<T>> Range<T> leftOpen(T from, T to) {
109110 * @return
110111 * @since 2.2
111112 */
112- public static <T extends Comparable < T > > Range <T > rightOpen (T from , T to ) {
113+ public static <T > Range <T > rightOpen (T from , T to ) {
113114 return new Range <>(Bound .inclusive (from ), Bound .exclusive (to ));
114115 }
115116
@@ -122,7 +123,7 @@ public static <T extends Comparable<T>> Range<T> rightOpen(T from, T to) {
122123 * @return
123124 * @since 2.2
124125 */
125- public static <T extends Comparable < T > > Range <T > leftUnbounded (Bound <T > to ) {
126+ public static <T > Range <T > leftUnbounded (Bound <T > to ) {
126127 return new Range <>(Bound .unbounded (), to );
127128 }
128129
@@ -135,7 +136,7 @@ public static <T extends Comparable<T>> Range<T> leftUnbounded(Bound<T> to) {
135136 * @return
136137 * @since 2.2
137138 */
138- public static <T extends Comparable < T > > Range <T > rightUnbounded (Bound <T > from ) {
139+ public static <T > Range <T > rightUnbounded (Bound <T > from ) {
139140 return new Range <>(from , Bound .unbounded ());
140141 }
141142
@@ -146,7 +147,7 @@ public static <T extends Comparable<T>> Range<T> rightUnbounded(Bound<T> from) {
146147 * @return
147148 * @since 2.0
148149 */
149- public static <T extends Comparable < T > > RangeBuilder <T > from (Bound <T > lower ) {
150+ public static <T > RangeBuilder <T > from (Bound <T > lower ) {
150151
151152 Assert .notNull (lower , "Lower bound must not be null!" );
152153 return new RangeBuilder <>(lower );
@@ -161,7 +162,7 @@ public static <T extends Comparable<T>> RangeBuilder<T> from(Bound<T> lower) {
161162 * @since 2.0
162163 * @see #from(Bound)
163164 */
164- public static <T extends Comparable < T > > Range <T > of (Bound <T > lowerBound , Bound <T > upperBound ) {
165+ public static <T > Range <T > of (Bound <T > lowerBound , Bound <T > upperBound ) {
165166 return new Range <>(lowerBound , upperBound );
166167 }
167168
@@ -171,9 +172,9 @@ public static <T extends Comparable<T>> Range<T> of(Bound<T> lowerBound, Bound<T
171172 * @param <T>
172173 * @param value must not be {@literal null}.
173174 * @return
174- * @see Range#closed(Comparable, Comparable )
175+ * @see Range#closed(Object, Object )
175176 */
176- public static <T extends Comparable < T > > Range <T > just (T value ) {
177+ public static <T > Range <T > just (T value ) {
177178 return Range .closed (value , value );
178179 }
179180
@@ -183,16 +184,34 @@ public static <T extends Comparable<T>> Range<T> just(T value) {
183184 * @param value must not be {@literal null}.
184185 * @return
185186 */
186- public boolean contains (T value ) {
187+ @ SuppressWarnings ({ "unchecked" })
188+ public boolean contains (Comparable <T > value ) {
189+
190+ return contains ((T ) value , (o1 , o2 ) -> {
191+
192+ Assert .isInstanceOf (Comparable .class , o1 ,
193+ "Range value must be an instance of Comparable to use contains(Comparable<T>)" );
194+ return ((Comparable <T >) o1 ).compareTo (o2 );
195+ });
196+ }
197+
198+ /**
199+ * Returns whether the {@link Range} contains the given value.
200+ *
201+ * @param value must not be {@literal null}.
202+ * @return
203+ * @since 3.0
204+ */
205+ public boolean contains (T value , Comparator <T > comparator ) {
187206
188207 Assert .notNull (value , "Reference value must not be null!" );
189208
190209 boolean greaterThanLowerBound = lowerBound .getValue () //
191- .map (it -> lowerBound .isInclusive () ? it . compareTo ( value ) <= 0 : it . compareTo ( value ) < 0 ) //
210+ .map (it -> lowerBound .isInclusive () ? comparator . compare ( it , value ) <= 0 : comparator . compare ( it , value ) < 0 ) //
192211 .orElse (true );
193212
194213 boolean lessThanUpperBound = upperBound .getValue () //
195- .map (it -> upperBound .isInclusive () ? it . compareTo ( value ) >= 0 : it . compareTo ( value ) > 0 ) //
214+ .map (it -> upperBound .isInclusive () ? comparator . compare ( it , value ) >= 0 : comparator . compare ( it , value ) > 0 ) //
196215 .orElse (true );
197216
198217 return greaterThanLowerBound && lessThanUpperBound ;
@@ -238,13 +257,13 @@ public int hashCode() {
238257
239258 /**
240259 * Value object representing a boundary. A boundary can either be {@link #unbounded() unbounded},
241- * {@link #inclusive(Comparable ) including its value} or {@link #exclusive(Comparable ) its value}.
260+ * {@link #inclusive(Object ) including its value} or {@link #exclusive(Object ) its value}.
242261 *
243262 * @author Mark Paluch
244263 * @since 2.0
245264 * @soundtrack Mohamed Ragab - Excelsior Sessions (March 2017)
246265 */
247- public static final class Bound <T extends Comparable < T > > {
266+ public static final class Bound <T > {
248267
249268 @ SuppressWarnings ({ "rawtypes" , "unchecked" }) //
250269 private static final Bound <?> UNBOUNDED = new Bound (Optional .empty (), true );
@@ -261,7 +280,7 @@ private Bound(Optional<T> value, boolean inclusive) {
261280 * Creates an unbounded {@link Bound}.
262281 */
263282 @ SuppressWarnings ("unchecked" )
264- public static <T extends Comparable < T > > Bound <T > unbounded () {
283+ public static <T > Bound <T > unbounded () {
265284 return (Bound <T >) UNBOUNDED ;
266285 }
267286
@@ -280,7 +299,7 @@ public boolean isBounded() {
280299 * @param value must not be {@literal null}.
281300 * @return
282301 */
283- public static <T extends Comparable < T > > Bound <T > inclusive (T value ) {
302+ public static <T > Bound <T > inclusive (T value ) {
284303
285304 Assert .notNull (value , "Value must not be null!" );
286305 return new Bound <>(Optional .of (value ), true );
@@ -332,7 +351,7 @@ public static Bound<Double> inclusive(double value) {
332351 * @param value must not be {@literal null}.
333352 * @return
334353 */
335- public static <T extends Comparable < T > > Bound <T > exclusive (T value ) {
354+ public static <T > Bound <T > exclusive (T value ) {
336355
337356 Assert .notNull (value , "Value must not be null!" );
338357 return new Bound <>(Optional .of (value ), false );
@@ -439,7 +458,7 @@ public int hashCode() {
439458 * @since 2.0
440459 * @soundtrack Aly and Fila - Future Sound Of Egypt 493
441460 */
442- public static class RangeBuilder <T extends Comparable < T > > {
461+ public static class RangeBuilder <T > {
443462
444463 private final Bound <T > lower ;
445464
0 commit comments