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 module hunt.util.Comparator;
13 
14 import std.traits;
15 debug import hunt.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) &lt;= 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 interface Comparator(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)&gt;0) &amp;&amp; (compare(y, z)&gt;0))</tt> implies
108      * <tt>compare(x, z)&gt;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     int compare(T o1, T o2) nothrow;
131 
132     // /**
133     //  * Indicates whether some other object is &quot;equal to&quot; this
134     //  * comparator.  This method must obey the general contract of
135     //  * {@link Object#equals(Object)}.  Additionally, this method can return
136     //  * <tt>true</tt> <i>only</i> if the specified object is also a comparator
137     //  * 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 reference
140     //  * <tt>o1</tt> and <tt>o2</tt>.<p>
141     //  *
142     //  * Note that it is <i>always</i> safe <i>not</i> to override
143     //  * <tt>Object.equals(Object)</tt>.  However, overriding this method may,
144     //  * in some cases, improve performance by allowing programs to determine
145     //  * 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 also
149     //  *          a comparator and it imposes the same ordering as this
150     //  *          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 this
158     //  * comparator.
159     //  *
160     //  * @return a comparator that imposes the reverse ordering of this
161     //  *         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 comparator
173     //  * is also serializable.
174     //  *
175     //  * @apiNote
176     //  * For example, to sort a collection of {@code string} based on the length
177     //  * and then case-insensitive natural ordering, the comparator can be
178     //  * composed using following code,
179     //  *
180     //  * <pre>{@code
181     //  *     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 comparator
186     //  *         compares two objects that are equal.
187     //  * @return a lexicographic-order comparator composed of this and then the
188     //  *         other comparator
189     //  * @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 that
201     //  * extracts a key to be compared with the given {@code Comparator}.
202     //  *
203     //  * @implSpec This implementation behaves as if {@code
204     //  *           thenComparing(comparing(keyExtractor, cmp))}.
205     //  *
206     //  * @param  !(U)  the type of the sort key
207     //  * @param  keyExtractor the function used to extract the sort key
208     //  * @param  keyComparator the {@code Comparator} used to compare the sort key
209     //  * @return a lexicographic-order comparator composed of this comparator
210     //  *         and then comparing on the key extracted by the keyExtractor function
211     //  * @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 that
224     //  * extracts a {@code Comparable} sort key.
225     //  *
226     //  * @implSpec This implementation behaves as if {@code
227     //  *           thenComparing(comparing(keyExtractor))}.
228     //  *
229     //  * @param  !(U)  the type of the {@link Comparable} sort key
230     //  * @param  keyExtractor the function used to extract the {@link
231     //  *         Comparable} sort key
232     //  * @return a lexicographic-order comparator composed of this and then the
233     //  *         {@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 that
246     //  * extracts a {@code int} sort key.
247     //  *
248     //  * @implSpec This implementation behaves as if {@code
249     //  *           thenComparing(comparingInt(keyExtractor))}.
250     //  *
251     //  * @param  keyExtractor the function used to extract the integer sort key
252     //  * @return a lexicographic-order comparator composed of this and then the
253     //  *         {@code int} sort key
254     //  * @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 that
264     //  * extracts a {@code long} sort key.
265     //  *
266     //  * @implSpec This implementation behaves as if {@code
267     //  *           thenComparing(comparingLong(keyExtractor))}.
268     //  *
269     //  * @param  keyExtractor the function used to extract the long sort key
270     //  * @return a lexicographic-order comparator composed of this and then the
271     //  *         {@code long} sort key
272     //  * @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 that
282     //  * extracts a {@code double} sort key.
283     //  *
284     //  * @implSpec This implementation behaves as if {@code
285     //  *           thenComparing(comparingDouble(keyExtractor))}.
286     //  *
287     //  * @param  keyExtractor the function used to extract the double sort key
288     //  * @return a lexicographic-order comparator composed of this and then the
289     //  *         {@code double} sort key
290     //  * @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>natural
300     //  * ordering</em>.
301     //  *
302     //  * <p>The returned comparator is serializable and throws {@link
303     //  * NullPointerException} when comparing {@code null}.
304     //  *
305     //  * @param  !(T) the {@link Comparable} type of element to be compared
306     //  * @return a comparator that imposes the reverse of the <i>natural
307     //  *         ordering</i> on {@code Comparable} objects.
308     //  * @see Comparable
309     //  */
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 natural
316     //  * order.
317     //  *
318     //  * <p>The returned comparator is serializable and throws {@link
319     //  * NullPointerException} when comparing {@code null}.
320     //  *
321     //  * @param  !(T) the {@link Comparable} type of element to be compared
322     //  * @return a comparator that imposes the <i>natural ordering</i> on {@code
323     //  *         Comparable} objects.
324     //  * @see Comparable
325     //  */
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 be
333     //  * less than non-null. When both are {@code null}, they are considered
334     //  * equal. If both are non-null, the specified {@code Comparator} is used
335     //  * 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 comparator
339     //  * is serializable.
340     //  *
341     //  * @param  !(T) the type of the elements to be compared
342     //  * @param  comparator a {@code Comparator} for comparing non-null values
343     //  * @return a comparator that considers {@code null} to be less than
344     //  *         non-null, and compares non-null objects with the supplied
345     //  *         {@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 be
353     //  * greater than non-null. When both are {@code null}, they are considered
354     //  * equal. If both are non-null, the specified {@code Comparator} is used
355     //  * 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 comparator
359     //  * is serializable.
360     //  *
361     //  * @param  !(T) the type of the elements to be compared
362     //  * @param  comparator a {@code Comparator} for comparing non-null values
363     //  * @return a comparator that considers {@code null} to be greater than
364     //  *         non-null, and compares non-null objects with the supplied
365     //  *         {@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}, and
373     //  * returns a {@code Comparator!(T)} that compares by that sort key using
374     //  * the specified {@link Comparator}.
375     //   *
376     //  * <p>The returned comparator is serializable if the specified function
377     //  * and comparator are both serializable.
378     //  *
379     //  * @apiNote
380     //  * For example, to obtain a {@code Comparator} that compares {@code
381     //  * Person} objects by their last name ignoring case differences,
382     //  *
383     //  * <pre>{@code
384     //  *     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 compared
390     //  * @param  !(U) the type of the sort key
391     //  * @param  keyExtractor the function used to extract the sort key
392     //  * @param  keyComparator the {@code Comparator} used to compare the sort key
393     //  * @return a comparator that compares by an extracted key using the
394     //  *         specified {@code Comparator}
395     //  * @throws NullPointerException if either argument is null
396     //  */
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.Comparable
410     //  * Comparable} sort key from a type {@code T}, and returns a {@code
411     //  * Comparator!(T)} that compares by that sort key.
412     //  *
413     //  * <p>The returned comparator is serializable if the specified function
414     //  * is also serializable.
415     //  *
416     //  * @apiNote
417     //  * For example, to obtain a {@code Comparator} that compares {@code
418     //  * Person} objects by their last name,
419     //  *
420     //  * <pre>{@code
421     //  *     Comparator<Person> byLastName = Comparator.comparing(Person::getLastName);
422     //  * }</pre>
423     //  *
424     //  * @param  !(T) the type of element to be compared
425     //  * @param  !(U) the type of the {@code Comparable} sort key
426     //  * @param  keyExtractor the function used to extract the {@link
427     //  *         Comparable} sort key
428     //  * @return a comparator that compares by an extracted key
429     //  * @throws NullPointerException if the argument is null
430     //  */
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 type
441     //  * {@code T}, and returns a {@code Comparator!(T)} that compares by that
442     //  * sort key.
443     //  *
444     //  * <p>The returned comparator is serializable if the specified function
445     //  * is also serializable.
446     //  *
447     //  * @param  !(T) the type of element to be compared
448     //  * @param  keyExtractor the function used to extract the integer sort key
449     //  * @return a comparator that compares by an extracted key
450     //  * @see #comparing(Function)
451     //  * @throws NullPointerException if the argument is null
452     //  */
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 type
461     //  * {@code T}, and returns a {@code Comparator!(T)} that compares by that
462     //  * sort key.
463     //  *
464     //  * <p>The returned comparator is serializable if the specified function is
465     //  * also serializable.
466     //  *
467     //  * @param  !(T) the type of element to be compared
468     //  * @param  keyExtractor the function used to extract the long sort key
469     //  * @return a comparator that compares by an extracted key
470     //  * @see #comparing(Function)
471     //  * @throws NullPointerException if the argument is null
472     //  */
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 type
481     //  * {@code T}, and returns a {@code Comparator!(T)} that compares by that
482     //  * sort key.
483     //  *
484     //  * <p>The returned comparator is serializable if the specified function
485     //  * is also serializable.
486     //  *
487     //  * @param  !(T) the type of element to be compared
488     //  * @param  keyExtractor the function used to extract the double sort key
489     //  * @return a comparator that compares by an extracted key
490     //  * @see #comparing(Function)
491     //  * @throws NullPointerException if the argument is null
492     //  */
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 int compare(T)(T x, T y) nothrow if(isOrderingComparable!(T)) {
502     try {
503         return (x < y) ? -1 : ((x == y) ? 0 : 1);
504     } catch(Exception ex) {
505         debug warning(ex.msg);
506         return 0;
507     }
508 }
509 
510 // FIXME: Needing refactor or cleanup -@zxp at 12/30/2018, 9:43:22 AM
511 // opCmp in a class, struct or interface should be nothrow.
512 bool lessThan(T)(ref T a, ref T b) nothrow if(isOrderingComparable!(T)) {
513     try {
514         return a < b;
515     } catch(Exception ex) {
516         debug warning(ex.msg);
517         return false;
518     }
519 }
520 
521 bool greaterthan(T)(ref T a, ref T b) nothrow if(isOrderingComparable!(T)) {
522     try {
523         return a > b;
524     } catch(Exception ex) {
525         debug warning(ex.msg);
526         return false;
527     }
528 }