1 /*
2 * Hunt - A refined core library for D programming language.
3 *
4 * Copyright (C) 2018-2019 HuntLabs
5 *
6 * Website: https://www.huntlabs.net/
7 *
8 * Licensed under the Apache-2.0 License.
9 *
10 */11 12 modulehunt.util.Comparator;
13 14 importstd.traits;
15 debugimporthunt.logging;
16 17 /**
18 * A comparison function, which imposes a <i>total ordering</i> on some
19 * collection of objects. Comparators can be passed to a sort method (such
20 * as {@link Collections#sort(List,Comparator) Collections.sort} or {@link
21 * Arrays#sort(Object[],Comparator) Arrays.sort}) to allow precise control
22 * over the sort order. Comparators can also be used to control the order of
23 * certain data structures (such as {@link SortedSet sorted sets} or {@link
24 * SortedMap sorted maps}), or to provide an ordering for collections of
25 * objects that don't have a {@link Comparable natural ordering}.<p>
26 *
27 * The ordering imposed by a comparator <tt>c</tt> on a set of elements
28 * <tt>S</tt> is said to be <i>consistent with equals</i> if and only if
29 * <tt>c.compare(e1, e2)==0</tt> has the same bool value as
30 * <tt>e1.equals(e2)</tt> for every <tt>e1</tt> and <tt>e2</tt> in
31 * <tt>S</tt>.<p>
32 *
33 * Caution should be exercised when using a comparator capable of imposing an
34 * ordering inconsistent with equals to order a sorted set (or sorted map).
35 * Suppose a sorted set (or sorted map) with an explicit comparator <tt>c</tt>
36 * is used with elements (or keys) drawn from a set <tt>S</tt>. If the
37 * ordering imposed by <tt>c</tt> on <tt>S</tt> is inconsistent with equals,
38 * the sorted set (or sorted map) will behave "strangely." In particular the
39 * sorted set (or sorted map) will violate the general contract for set (or
40 * map), which is defined in terms of <tt>equals</tt>.<p>
41 *
42 * For example, suppose one adds two elements {@code a} and {@code b} such that
43 * {@code (a.equals(b) && c.compare(a, b) != 0)}
44 * to an empty {@code TreeSet} with comparator {@code c}.
45 * The second {@code add} operation will return
46 * true (and the size of the tree set will increase) because {@code a} and
47 * {@code b} are not equivalent from the tree set's perspective, even though
48 * this is contrary to the specification of the
49 * {@link Set#add Set.add} method.<p>
50 *
51 * Note: It is generally a good idea for comparators to also implement
52 * <tt>java.io.Serializable</tt>, as they may be used as ordering methods in
53 * serializable data structures (like {@link TreeSet}, {@link TreeMap}). In
54 * order for the data structure to serialize successfully, the comparator (if
55 * provided) must implement <tt>Serializable</tt>.<p>
56 *
57 * For the mathematically inclined, the <i>relation</i> that defines the
58 * <i>imposed ordering</i> that a given comparator <tt>c</tt> imposes on a
59 * given set of objects <tt>S</tt> is:<pre>
60 * {(x, y) such that c.compare(x, y) <= 0}.
61 * </pre> The <i>quotient</i> for this total order is:<pre>
62 * {(x, y) such that c.compare(x, y) == 0}.
63 * </pre>
64 *
65 * It follows immediately from the contract for <tt>compare</tt> that the
66 * quotient is an <i>equivalence relation</i> on <tt>S</tt>, and that the
67 * imposed ordering is a <i>total order</i> on <tt>S</tt>. When we say that
68 * the ordering imposed by <tt>c</tt> on <tt>S</tt> is <i>consistent with
69 * equals</i>, we mean that the quotient for the ordering is the equivalence
70 * relation defined by the objects' {@link Object#equals(Object)
71 * equals(Object)} method(s):<pre>
72 * {(x, y) such that x.equals(y)}. </pre>
73 *
74 * <p>Unlike {@code Comparable}, a comparator may optionally permit
75 * comparison of null arguments, while maintaining the requirements for
76 * an equivalence relation.
77 *
78 * <p>This interface is a member of the
79 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
80 * Java Collections Framework</a>.
81 *
82 * @param (T) the type of objects that may be compared by this comparator
83 *
84 * @author Josh Bloch
85 * @author Neal Gafter
86 * @see Comparable
87 * @see java.io.Serializable
88 */89 interfaceComparator(T) {
90 /**
91 * Compares its two arguments for order. Returns a negative integer,
92 * zero, or a positive integer as the first argument is less than, equal
93 * to, or greater than the second.<p>
94 *
95 * In the foregoing description, the notation
96 * <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
97 * <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
98 * <tt>0</tt>, or <tt>1</tt> according to whether the value of
99 * <i>expression</i> is negative, zero or positive.<p>
100 *
101 * The implementor must ensure that <tt>sgn(compare(x, y)) ==
102 * -sgn(compare(y, x))</tt> for all <tt>x</tt> and <tt>y</tt>. (This
103 * implies that <tt>compare(x, y)</tt> must throw an exception if and only
104 * if <tt>compare(y, x)</tt> throws an exception.)<p>
105 *
106 * The implementor must also ensure that the relation is transitive:
107 * <tt>((compare(x, y)>0) && (compare(y, z)>0))</tt> implies
108 * <tt>compare(x, z)>0</tt>.<p>
109 *
110 * Finally, the implementor must ensure that <tt>compare(x, y)==0</tt>
111 * implies that <tt>sgn(compare(x, z))==sgn(compare(y, z))</tt> for all
112 * <tt>z</tt>.<p>
113 *
114 * It is generally the case, but <i>not</i> strictly required that
115 * <tt>(compare(x, y)==0) == (x.equals(y))</tt>. Generally speaking,
116 * any comparator that violates this condition should clearly indicate
117 * this fact. The recommended language is "Note: this comparator
118 * imposes orderings that are inconsistent with equals."
119 *
120 * @param o1 the first object to be compared.
121 * @param o2 the second object to be compared.
122 * @return a negative integer, zero, or a positive integer as the
123 * first argument is less than, equal to, or greater than the
124 * second.
125 * @throws NullPointerException if an argument is null and this
126 * comparator does not permit null arguments
127 * @throws ClassCastException if the arguments' types prevent them from
128 * being compared by this comparator.
129 */130 intcompare(To1, To2) nothrow;
131 132 // /**133 // * Indicates whether some other object is "equal to" this134 // * comparator. This method must obey the general contract of135 // * {@link Object#equals(Object)}. Additionally, this method can return136 // * <tt>true</tt> <i>only</i> if the specified object is also a comparator137 // * and it imposes the same ordering as this comparator. Thus,138 // * <code>comp1.equals(comp2)</code> implies that <tt>sgn(comp1.compare(o1,139 // * o2))==sgn(comp2.compare(o1, o2))</tt> for every object reference140 // * <tt>o1</tt> and <tt>o2</tt>.<p>141 // *142 // * Note that it is <i>always</i> safe <i>not</i> to override143 // * <tt>Object.equals(Object)</tt>. However, overriding this method may,144 // * in some cases, improve performance by allowing programs to determine145 // * that two distinct comparators impose the same order.146 // *147 // * @param obj the reference object with which to compare.148 // * @return <code>true</code> only if the specified object is also149 // * a comparator and it imposes the same ordering as this150 // * comparator.151 // * @see Object#equals(Object)152 // * @see Object#hashCode()153 // */154 // bool equals(Object obj);155 156 // /**157 // * Returns a comparator that imposes the reverse ordering of this158 // * comparator.159 // *160 // * @return a comparator that imposes the reverse ordering of this161 // * comparator.162 // */163 // Comparator!(T) reversed() {164 // return Collections.reverseOrder(this);165 // }166 167 // /**168 // * Returns a lexicographic-order comparator with another comparator.169 // * If this {@code Comparator} considers two elements equal, i.e.170 // * {@code compare(a, b) == 0}, {@code other} is used to determine the order.171 // *172 // * <p>The returned comparator is serializable if the specified comparator173 // * is also serializable.174 // *175 // * @apiNote176 // * For example, to sort a collection of {@code string} based on the length177 // * and then case-insensitive natural ordering, the comparator can be178 // * composed using following code,179 // *180 // * <pre>{@code181 // * Comparator<string> cmp = Comparator.comparingInt(string::length)182 // * .thenComparing(string.CASE_INSENSITIVE_ORDER);183 // * }</pre>184 // *185 // * @param other the other comparator to be used when this comparator186 // * compares two objects that are equal.187 // * @return a lexicographic-order comparator composed of this and then the188 // * other comparator189 // * @throws NullPointerException if the argument is null.190 // */191 // Comparator!(T) thenComparing(Comparator<T> other) {192 // Objects.requireNonNull(other);193 // return (Comparator!(T) & Serializable) (c1, c2) -> {194 // int res = compare(c1, c2);195 // return (res != 0) ? res : other.compare(c1, c2);196 // };197 // }198 199 // /**200 // * Returns a lexicographic-order comparator with a function that201 // * extracts a key to be compared with the given {@code Comparator}.202 // *203 // * @implSpec This implementation behaves as if {@code204 // * thenComparing(comparing(keyExtractor, cmp))}.205 // *206 // * @param !(U) the type of the sort key207 // * @param keyExtractor the function used to extract the sort key208 // * @param keyComparator the {@code Comparator} used to compare the sort key209 // * @return a lexicographic-order comparator composed of this comparator210 // * and then comparing on the key extracted by the keyExtractor function211 // * @throws NullPointerException if either argument is null.212 // * @see #comparing(Function, Comparator)213 // * @see #thenComparing(Comparator)214 // */215 // !(U) Comparator!(T) thenComparing(216 // Function<T, U> keyExtractor,217 // Comparator<U> keyComparator)218 // {219 // return thenComparing(comparing(keyExtractor, keyComparator));220 // }221 222 // /**223 // * Returns a lexicographic-order comparator with a function that224 // * extracts a {@code Comparable} sort key.225 // *226 // * @implSpec This implementation behaves as if {@code227 // * thenComparing(comparing(keyExtractor))}.228 // *229 // * @param !(U) the type of the {@link Comparable} sort key230 // * @param keyExtractor the function used to extract the {@link231 // * Comparable} sort key232 // * @return a lexicographic-order comparator composed of this and then the233 // * {@link Comparable} sort key.234 // * @throws NullPointerException if the argument is null.235 // * @see #comparing(Function)236 // * @see #thenComparing(Comparator)237 // */238 // <U extends Comparable<U>> Comparator!(T) thenComparing(239 // Function<T, U> keyExtractor)240 // {241 // return thenComparing(comparing(keyExtractor));242 // }243 244 // /**245 // * Returns a lexicographic-order comparator with a function that246 // * extracts a {@code int} sort key.247 // *248 // * @implSpec This implementation behaves as if {@code249 // * thenComparing(comparingInt(keyExtractor))}.250 // *251 // * @param keyExtractor the function used to extract the integer sort key252 // * @return a lexicographic-order comparator composed of this and then the253 // * {@code int} sort key254 // * @throws NullPointerException if the argument is null.255 // * @see #comparingInt(ToIntFunction)256 // * @see #thenComparing(Comparator)257 // */258 // Comparator!(T) thenComparingInt(ToIntFunction<T> keyExtractor) {259 // return thenComparing(comparingInt(keyExtractor));260 // }261 262 // /**263 // * Returns a lexicographic-order comparator with a function that264 // * extracts a {@code long} sort key.265 // *266 // * @implSpec This implementation behaves as if {@code267 // * thenComparing(comparingLong(keyExtractor))}.268 // *269 // * @param keyExtractor the function used to extract the long sort key270 // * @return a lexicographic-order comparator composed of this and then the271 // * {@code long} sort key272 // * @throws NullPointerException if the argument is null.273 // * @see #comparingLong(ToLongFunction)274 // * @see #thenComparing(Comparator)275 // */276 // Comparator!(T) thenComparingLong(ToLongFunction<T> keyExtractor) {277 // return thenComparing(comparingLong(keyExtractor));278 // }279 280 // /**281 // * Returns a lexicographic-order comparator with a function that282 // * extracts a {@code double} sort key.283 // *284 // * @implSpec This implementation behaves as if {@code285 // * thenComparing(comparingDouble(keyExtractor))}.286 // *287 // * @param keyExtractor the function used to extract the double sort key288 // * @return a lexicographic-order comparator composed of this and then the289 // * {@code double} sort key290 // * @throws NullPointerException if the argument is null.291 // * @see #comparingDouble(ToDoubleFunction)292 // * @see #thenComparing(Comparator)293 // */294 // Comparator!(T) thenComparingDouble(ToDoubleFunction<T> keyExtractor) {295 // return thenComparing(comparingDouble(keyExtractor));296 // }297 298 // /**299 // * Returns a comparator that imposes the reverse of the <em>natural300 // * ordering</em>.301 // *302 // * <p>The returned comparator is serializable and throws {@link303 // * NullPointerException} when comparing {@code null}.304 // *305 // * @param !(T) the {@link Comparable} type of element to be compared306 // * @return a comparator that imposes the reverse of the <i>natural307 // * ordering</i> on {@code Comparable} objects.308 // * @see Comparable309 // */310 // static <T extends Comparable<T>> Comparator!(T) reverseOrder() {311 // return Collections.reverseOrder();312 // }313 314 // /**315 // * Returns a comparator that compares {@link Comparable} objects in natural316 // * order.317 // *318 // * <p>The returned comparator is serializable and throws {@link319 // * NullPointerException} when comparing {@code null}.320 // *321 // * @param !(T) the {@link Comparable} type of element to be compared322 // * @return a comparator that imposes the <i>natural ordering</i> on {@code323 // * Comparable} objects.324 // * @see Comparable325 // */326 // @SuppressWarnings("unchecked")327 // static <T extends Comparable<T>> Comparator!(T) naturalOrder() {328 // return (Comparator!(T)) Comparators.NaturalOrderComparator.INSTANCE;329 // }330 331 // /**332 // * Returns a null-friendly comparator that considers {@code null} to be333 // * less than non-null. When both are {@code null}, they are considered334 // * equal. If both are non-null, the specified {@code Comparator} is used335 // * to determine the order. If the specified comparator is {@code null},336 // * then the returned comparator considers all non-null values to be equal.337 // *338 // * <p>The returned comparator is serializable if the specified comparator339 // * is serializable.340 // *341 // * @param !(T) the type of the elements to be compared342 // * @param comparator a {@code Comparator} for comparing non-null values343 // * @return a comparator that considers {@code null} to be less than344 // * non-null, and compares non-null objects with the supplied345 // * {@code Comparator}.346 // */347 // static !(T) Comparator!(T) nullsFirst(Comparator<T> comparator) {348 // return new Comparators.NullComparator<>(true, comparator);349 // }350 351 // /**352 // * Returns a null-friendly comparator that considers {@code null} to be353 // * greater than non-null. When both are {@code null}, they are considered354 // * equal. If both are non-null, the specified {@code Comparator} is used355 // * to determine the order. If the specified comparator is {@code null},356 // * then the returned comparator considers all non-null values to be equal.357 // *358 // * <p>The returned comparator is serializable if the specified comparator359 // * is serializable.360 // *361 // * @param !(T) the type of the elements to be compared362 // * @param comparator a {@code Comparator} for comparing non-null values363 // * @return a comparator that considers {@code null} to be greater than364 // * non-null, and compares non-null objects with the supplied365 // * {@code Comparator}.366 // */367 // static !(T) Comparator!(T) nullsLast(Comparator<T> comparator) {368 // return new Comparators.NullComparator<>(false, comparator);369 // }370 371 // /**372 // * Accepts a function that extracts a sort key from a type {@code T}, and373 // * returns a {@code Comparator!(T)} that compares by that sort key using374 // * the specified {@link Comparator}.375 // *376 // * <p>The returned comparator is serializable if the specified function377 // * and comparator are both serializable.378 // *379 // * @apiNote380 // * For example, to obtain a {@code Comparator} that compares {@code381 // * Person} objects by their last name ignoring case differences,382 // *383 // * <pre>{@code384 // * Comparator<Person> cmp = Comparator.comparing(385 // * Person::getLastName,386 // * string.CASE_INSENSITIVE_ORDER);387 // * }</pre>388 // *389 // * @param !(T) the type of element to be compared390 // * @param !(U) the type of the sort key391 // * @param keyExtractor the function used to extract the sort key392 // * @param keyComparator the {@code Comparator} used to compare the sort key393 // * @return a comparator that compares by an extracted key using the394 // * specified {@code Comparator}395 // * @throws NullPointerException if either argument is null396 // */397 // static <T, U> Comparator!(T) comparing(398 // Function<T, U> keyExtractor,399 // Comparator<U> keyComparator)400 // {401 // Objects.requireNonNull(keyExtractor);402 // Objects.requireNonNull(keyComparator);403 // return (Comparator!(T) & Serializable)404 // (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),405 // keyExtractor.apply(c2));406 // }407 408 // /**409 // * Accepts a function that extracts a {@link java.lang.Comparable410 // * Comparable} sort key from a type {@code T}, and returns a {@code411 // * Comparator!(T)} that compares by that sort key.412 // *413 // * <p>The returned comparator is serializable if the specified function414 // * is also serializable.415 // *416 // * @apiNote417 // * For example, to obtain a {@code Comparator} that compares {@code418 // * Person} objects by their last name,419 // *420 // * <pre>{@code421 // * Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);422 // * }</pre>423 // *424 // * @param !(T) the type of element to be compared425 // * @param !(U) the type of the {@code Comparable} sort key426 // * @param keyExtractor the function used to extract the {@link427 // * Comparable} sort key428 // * @return a comparator that compares by an extracted key429 // * @throws NullPointerException if the argument is null430 // */431 // static <T, U extends Comparable<U>> Comparator!(T) comparing(432 // Function<T, U> keyExtractor)433 // {434 // Objects.requireNonNull(keyExtractor);435 // return (Comparator!(T) & Serializable)436 // (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));437 // }438 439 // /**440 // * Accepts a function that extracts an {@code int} sort key from a type441 // * {@code T}, and returns a {@code Comparator!(T)} that compares by that442 // * sort key.443 // *444 // * <p>The returned comparator is serializable if the specified function445 // * is also serializable.446 // *447 // * @param !(T) the type of element to be compared448 // * @param keyExtractor the function used to extract the integer sort key449 // * @return a comparator that compares by an extracted key450 // * @see #comparing(Function)451 // * @throws NullPointerException if the argument is null452 // */453 // static !(T) Comparator!(T) comparingInt(ToIntFunction<T> keyExtractor) {454 // Objects.requireNonNull(keyExtractor);455 // return (Comparator!(T) & Serializable)456 // (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));457 // }458 459 // /**460 // * Accepts a function that extracts a {@code long} sort key from a type461 // * {@code T}, and returns a {@code Comparator!(T)} that compares by that462 // * sort key.463 // *464 // * <p>The returned comparator is serializable if the specified function is465 // * also serializable.466 // *467 // * @param !(T) the type of element to be compared468 // * @param keyExtractor the function used to extract the long sort key469 // * @return a comparator that compares by an extracted key470 // * @see #comparing(Function)471 // * @throws NullPointerException if the argument is null472 // */473 // static !(T) Comparator!(T) comparingLong(ToLongFunction<T> keyExtractor) {474 // Objects.requireNonNull(keyExtractor);475 // return (Comparator!(T) & Serializable)476 // (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));477 // }478 479 // /**480 // * Accepts a function that extracts a {@code double} sort key from a type481 // * {@code T}, and returns a {@code Comparator!(T)} that compares by that482 // * sort key.483 // *484 // * <p>The returned comparator is serializable if the specified function485 // * is also serializable.486 // *487 // * @param !(T) the type of element to be compared488 // * @param keyExtractor the function used to extract the double sort key489 // * @return a comparator that compares by an extracted key490 // * @see #comparing(Function)491 // * @throws NullPointerException if the argument is null492 // */493 // static!(T) Comparator!(T) comparingDouble(ToDoubleFunction<T> keyExtractor) {494 // Objects.requireNonNull(keyExtractor);495 // return (Comparator!(T) & Serializable)496 // (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));497 // }498 }
499 500 501 intcompare(T)(Tx, Ty) nothrowif(isOrderingComparable!(T)) {
502 try {
503 return (x < y) ? -1 : ((x == y) ? 0 : 1);
504 } catch(Exceptionex) {
505 debugwarning(ex.msg);
506 return0;
507 }
508 }
509 510 // FIXME: Needing refactor or cleanup -@zxp at 12/30/2018, 9:43:22 AM511 // opCmp in a class, struct or interface should be nothrow.512 boollessThan(T)(refTa, refTb) nothrowif(isOrderingComparable!(T)) {
513 try {
514 returna < b;
515 } catch(Exceptionex) {
516 debugwarning(ex.msg);
517 returnfalse;
518 }
519 }
520 521 boolgreaterthan(T)(refTa, refTb) nothrowif(isOrderingComparable!(T)) {
522 try {
523 returna > b;
524 } catch(Exceptionex) {
525 debugwarning(ex.msg);
526 returnfalse;
527 }
528 }