FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
utils/src/main/java/dev/simplified/util/Range.java at master · simplified-dev/utils · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
simplified-dev
/
utils
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
0
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
utils
/
src
/
main
/
java
/
dev
/
simplified
/
util
/
Range.java
Copy path
More file actions
More file actions
Latest commit
History
History
History
406 lines (363 loc) · 15.5 KB
Breadcrumbs
utils
/
src
/
main
/
java
/
dev
/
simplified
/
util
/
Range.java
Copy path
File metadata and controls
406 lines (363 loc) · 15.5 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
package
dev
.
simplified
.
util
;
import
dev
.
simplified
.
annotations
.
EqualsAndHashCode
;
import
dev
.
simplified
.
annotations
.
Getter
;
import
org
.
jetbrains
.
annotations
.
NotNull
;
import
org
.
jetbrains
.
annotations
.
Nullable
;
import
java
.
io
.
Serializable
;
import
java
.
util
.
Comparator
;
import
java
.
util
.
Objects
;
/**
* An immutable range of objects from a minimum to maximum point, both inclusive.
* <p>
* The elements must either implement {@link Comparable} (natural ordering) or a custom
* {@link Comparator} must be supplied at construction time. The factory methods
* {@link #between(Comparable, Comparable)} and {@link #is(Comparable)} automatically
* normalize the element order so that {@link #getMinimum()} and {@link #getMaximum()}
* always return the correct bounds regardless of argument order.
* <p>
* This class is thread-safe provided that the contained objects and the comparator are
* also thread-safe.
*
* @param <T> the type of range values
* @see Comparable
* @see Comparator
*/
@
Getter
@
EqualsAndHashCode
(
of
= {
"minimum"
,
"maximum"
},
cacheHashCode
=
true
)
public
final
class
Range
<
T
>
implements
Serializable
{
/**
* Creates a range with the specified minimum and maximum values (both inclusive),
* using the natural ordering of the elements.
* <p>
* The arguments may be passed in either order; the minimum and maximum will be
* determined automatically.
*
* @param <T> the type of the elements in the range
* @param fromInclusive the first boundary of the range, inclusive
* @param toInclusive the second boundary of the range, inclusive
* @return a new range spanning from the lesser to the greater element
* @throws ClassCastException if the elements are not {@link Comparable}
*/
public
static
<
T
extends
Comparable
<
T
>>
@
NotNull
Range
<
T
>
between
(
@
NotNull
T
fromInclusive
,
@
NotNull
T
toInclusive
) {
return
between
(
fromInclusive
,
toInclusive
,
null
);
}
/**
* Creates a range with the specified minimum and maximum values (both inclusive),
* using the given comparator to determine element order.
* <p>
* The arguments may be passed in either order; the minimum and maximum will be
* determined automatically via the comparator. If the comparator is {@code null},
* natural ordering is used.
*
* @param <T> the type of the elements in the range
* @param fromInclusive the first boundary of the range, inclusive
* @param toInclusive the second boundary of the range, inclusive
* @param comparator the comparator to use for ordering, or {@code null} for natural ordering
* @return a new range spanning from the lesser to the greater element
* @throws ClassCastException if using natural ordering and the elements are not {@link Comparable}
*/
public
static
<
T
>
@
NotNull
Range
<
T
>
between
(
@
NotNull
T
fromInclusive
,
@
NotNull
T
toInclusive
,
@
Nullable
Comparator
<
T
>
comparator
) {
return
new
Range
<>(
fromInclusive
,
toInclusive
,
comparator
);
}
/**
* Creates a range containing exactly one element, using the natural ordering of the element.
* <p>
* The returned range has equal minimum and maximum values.
*
* @param <T> the type of the element in the range
* @param element the single element defining both boundaries of the range
* @return a new range where minimum and maximum are both the given element
* @throws ClassCastException if the element is not {@link Comparable}
*/
public
static
<
T
extends
Comparable
<
T
>>
@
NotNull
Range
<
T
>
is
(
@
NotNull
T
element
) {
return
between
(
element
,
element
,
null
);
}
/**
* Creates a range containing exactly one element, using the given comparator.
* <p>
* The returned range has equal minimum and maximum values. If the comparator is
* {@code null}, natural ordering is used.
*
* @param <T> the type of the element in the range
* @param element the single element defining both boundaries of the range
* @param comparator the comparator to use for ordering, or {@code null} for natural ordering
* @return a new range where minimum and maximum are both the given element
* @throws ClassCastException if using natural ordering and the element is not {@link Comparable}
*/
public
static
<
T
>
@
NotNull
Range
<
T
>
is
(
@
NotNull
T
element
,
@
Nullable
Comparator
<
T
>
comparator
) {
return
between
(
element
,
element
,
comparator
);
}
/**
* The comparator used to order elements within this range; never {@code null} (natural ordering uses an internal implementation).
*/
private
final
@
NotNull
Comparator
<
T
>
comparator
;
/**
* The maximum (upper bound) value in this range, inclusive.
*/
private
final
@
NotNull
T
maximum
;
/**
* The minimum (lower bound) value in this range, inclusive.
*/
private
final
@
NotNull
T
minimum
;
/**
* Creates a new range between the two given elements, using the given comparator
* to determine which is the minimum and which is the maximum.
*
* @param element1 the first element
* @param element2 the second element
* @param comp the comparator to use, or {@code null} for natural ordering
*/
@
SuppressWarnings
(
"unchecked"
)
private
Range
(
@
NotNull
T
element1
,
@
NotNull
T
element2
,
@
Nullable
Comparator
<
T
>
comp
) {
this
.
comparator
=
Objects
.
requireNonNullElse
(
comp
,
ComparableComparator
.
INSTANCE
);
if
(
this
.
comparator
.
compare
(
element1
,
element2
) <
1
) {
this
.
minimum
=
element1
;
this
.
maximum
=
element2
;
}
else
{
this
.
minimum
=
element2
;
this
.
maximum
=
element1
;
}
}
/**
* Checks whether the specified element falls within this range (inclusive on both ends).
*
* @param element the element to check, {@code null} returns {@code false}
* @return {@code true} if the element is within this range, {@code false} otherwise
*/
public
boolean
contains
(
@
Nullable
final
T
element
) {
if
(
element
==
null
)
return
false
;
return
comparator
.
compare
(
element
,
minimum
) > -
1
&&
comparator
.
compare
(
element
,
maximum
) <
1
;
}
/**
* Checks whether this range fully contains the specified other range.
* <p>
* This method may fail if the ranges use different comparators or element types.
*
* @param otherRange the range to check, {@code null} returns {@code false}
* @return {@code true} if this range contains every element of the other range, {@code false} otherwise
* @throws RuntimeException if the ranges cannot be compared
*/
public
boolean
containsRange
(
@
Nullable
final
Range
<
T
>
otherRange
) {
if
(
otherRange
==
null
)
return
false
;
return
contains
(
otherRange
.
minimum
) &&
contains
(
otherRange
.
maximum
);
}
/**
* Determines the position of the specified element relative to this range.
* <p>
* Returns {@code -1} if the element is below the range minimum, {@code 0} if the element
* is contained within the range, and {@code 1} if the element is above the range maximum.
*
* @param element the element to compare against this range
* @return {@code -1}, {@code 0}, or {@code 1} depending on whether the element is before,
* within, or after this range
*/
public
int
elementCompareTo
(
@
NotNull
final
T
element
) {
if
(
isAfter
(
element
))
return
-
1
;
else
if
(
isBefore
(
element
))
return
1
;
else
return
0
;
}
/**
* Computes the intersection of this range with the given overlapping range.
* <p>
* If the two ranges are equal, this range is returned as-is.
*
* @param other the overlapping range to intersect with
* @return a new range representing the intersection, or this range if the two are equal
* @throws IllegalArgumentException if the given range does not overlap this range
*/
public
@
NotNull
Range
<
T
>
intersectionWith
(
@
NotNull
final
Range
<
T
>
other
) {
if
(!
this
.
isOverlappedBy
(
other
))
throw
new
IllegalArgumentException
(
String
.
format
(
"Cannot calculate intersection with non-overlapping range %s"
,
other
));
if
(
this
.
equals
(
other
))
return
this
;
final
T
min
=
getComparator
().
compare
(
minimum
,
other
.
minimum
) <
0
?
other
.
minimum
:
minimum
;
final
T
max
=
getComparator
().
compare
(
maximum
,
other
.
maximum
) <
0
?
maximum
:
other
.
maximum
;
return
between
(
min
,
max
,
getComparator
());
}
/**
* Checks whether this range is entirely after the specified element (i.e., the element is
* below the range minimum).
*
* @param element the element to check, {@code null} returns {@code false}
* @return {@code true} if this range is entirely after the specified element
*/
public
boolean
isAfter
(
@
Nullable
final
T
element
) {
if
(
element
==
null
)
return
false
;
return
comparator
.
compare
(
element
,
minimum
) <
0
;
}
/**
* Checks whether this range is completely after the specified other range.
* <p>
* This method may fail if the ranges use different comparators or element types.
*
* @param otherRange the range to check, {@code null} returns {@code false}
* @return {@code true} if this range is entirely after the other range
* @throws RuntimeException if the ranges cannot be compared
*/
public
boolean
isAfterRange
(
@
Nullable
final
Range
<
T
>
otherRange
) {
if
(
otherRange
==
null
)
return
false
;
return
isAfter
(
otherRange
.
maximum
);
}
/**
* Checks whether this range is entirely before the specified element (i.e., the element is
* above the range maximum).
*
* @param element the element to check, {@code null} returns {@code false}
* @return {@code true} if this range is entirely before the specified element
*/
public
boolean
isBefore
(
@
Nullable
final
T
element
) {
if
(
element
==
null
)
return
false
;
return
comparator
.
compare
(
element
,
maximum
) >
0
;
}
/**
* Checks whether this range is completely before the specified other range.
* <p>
* This method may fail if the ranges use different comparators or element types.
*
* @param otherRange the range to check, {@code null} returns {@code false}
* @return {@code true} if this range is entirely before the other range
* @throws RuntimeException if the ranges cannot be compared
*/
public
boolean
isBeforeRange
(
@
Nullable
final
Range
<
T
>
otherRange
) {
if
(
otherRange
==
null
)
return
false
;
return
isBefore
(
otherRange
.
minimum
);
}
/**
* Checks whether the specified element is equal to the maximum of this range.
*
* @param element the element to check, {@code null} returns {@code false}
* @return {@code true} if the element equals the range maximum
*/
public
boolean
isEndedBy
(
@
Nullable
final
T
element
) {
if
(
element
==
null
)
return
false
;
return
comparator
.
compare
(
element
,
maximum
) ==
0
;
}
/**
* Checks whether this range uses the natural ordering of its elements.
* <p>
* Natural ordering is indicated by the use of an internal {@link Comparable}-based comparator.
* This method is the only way to determine whether a {@code null} comparator was supplied
* at construction time.
*
* @return {@code true} if this range uses natural ordering, {@code false} if a custom comparator was provided
*/
public
boolean
isNaturalOrdering
() {
return
comparator
==
Range
.
ComparableComparator
.
INSTANCE
;
}
/**
* Checks whether this range is overlapped by the specified other range.
* <p>
* Two ranges overlap if they share at least one element in common.
* This method may fail if the ranges use different comparators or element types.
*
* @param otherRange the range to test, {@code null} returns {@code false}
* @return {@code true} if the specified range overlaps with this range
* @throws RuntimeException if the ranges cannot be compared
*/
public
boolean
isOverlappedBy
(
@
Nullable
final
Range
<
T
>
otherRange
) {
if
(
otherRange
==
null
)
return
false
;
return
otherRange
.
contains
(
minimum
)
||
otherRange
.
contains
(
maximum
)
||
contains
(
otherRange
.
minimum
);
}
/**
* Checks whether the specified element is equal to the minimum of this range.
*
* @param element the element to check, {@code null} returns {@code false}
* @return {@code true} if the element equals the range minimum
*/
public
boolean
isStartedBy
(
@
Nullable
final
T
element
) {
if
(
element
==
null
)
return
false
;
return
comparator
.
compare
(
element
,
minimum
) ==
0
;
}
/**
* Clamps the given element to this range by returning the element itself if it falls
* within the range, the range minimum if the element is below it, or the range maximum
* if the element is above it.
*
* <pre><code>
* Range<Integer> range = Range.between(16, 64);
* range.fit(-9) --> 16
* range.fit(0) --> 16
* range.fit(15) --> 16
* range.fit(16) --> 16
* range.fit(17) --> 17
* ...
* range.fit(63) --> 63
* range.fit(64) --> 64
* range.fit(99) --> 64
* </code></pre>
*
* @param element the element to clamp
* @return the minimum, the element, or the maximum depending on the element's position relative to this range
* @throws NullPointerException if the element is {@code null}
*/
public
@
NotNull
T
fit
(
@
NotNull
final
T
element
) {
if
(
isAfter
(
element
))
return
minimum
;
else
if
(
isBefore
(
element
))
return
maximum
;
else
return
element
;
}
/**
* Returns a string representation of this range in the format {@code [min..max]}.
*
* @return a string representation of this range
*/
@
Override
public
@
NotNull
String
toString
() {
return
"["
+
minimum
+
".."
+
maximum
+
"]"
;
}
/**
* Returns a formatted string representation of this range using the given format string.
* <p>
* The format string may contain the following placeholders:
* <ul>
* <li>{@code %1$s} for the minimum element</li>
* <li>{@code %2$s} for the maximum element</li>
* <li>{@code %3$s} for the comparator</li>
* </ul>
* The default format used by {@link #toString()} is {@code [%1$s..%2$s]}.
*
* @param format the format string
* @return the formatted string representation
*/
public
@
NotNull
String
toString
(
@
NotNull
final
String
format
) {
return
String
.
format
(
format
,
minimum
,
maximum
,
comparator
);
}
/**
* Internal comparator that delegates to {@link Comparable#compareTo(Object)} for natural ordering.
*/
@
SuppressWarnings
({
"rawtypes"
,
"unchecked"
})
private
enum
ComparableComparator
implements
Comparator
{
/**
* Singleton instance.
*/
INSTANCE
;
/**
* Compares two {@link Comparable} objects using their natural ordering.
*
* @param obj1 the first object to compare
* @param obj2 the second object to compare
* @return a negative integer, zero, or a positive integer as the first object is less than,
* equal to, or greater than the second
*/
@
Override
public
int
compare
(
final
Object
obj1
,
final
Object
obj2
) {
return
((
Comparable
)
obj1
).
compareTo
(
obj2
);
}
}
}
Back
|
FazBrowse Home
|
New Git URL