Skip to content

Commit ffb4c27

Browse files
7h3kk1djnape
authored andcommitted
Add utility functions for interoperability with java.util.Comparator
- Add ComparisonRelation to encapsulate Comparator/Comparable#compare semantics - Add Compare to abstract over Comparator#compare using ComparisonRelation - Add comparator compatible functions (CmpEqWith, GTEWith, GTWith, LTEWith, LTWith)
1 parent c87ac5b commit ffb4c27

File tree

24 files changed

+763
-7
lines changed

24 files changed

+763
-7
lines changed

src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/CmpEqBy.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
77
import com.jnape.palatable.lambda.functions.specialized.Predicate;
88

9+
import static com.jnape.palatable.lambda.functions.builtin.fn3.CmpEqWith.cmpEqWith;
910
import static com.jnape.palatable.lambda.functions.specialized.Predicate.predicate;
11+
import static java.util.Comparator.comparing;
1012

1113
/**
1214
* Given a mapping function from some type <code>A</code> to some {@link Comparable} type <code>B</code> and two values
@@ -16,6 +18,7 @@
1618
* @param <A> the value type
1719
* @param <B> the mapped comparison type
1820
* @see CmpEq
21+
* @see CmpEqWith
1922
* @see LTBy
2023
* @see GTBy
2124
*/
@@ -28,7 +31,7 @@ private CmpEqBy() {
2831

2932
@Override
3033
public Boolean checkedApply(Fn1<? super A, ? extends B> compareFn, A x, A y) {
31-
return compareFn.apply(x).compareTo(compareFn.apply(y)) == 0;
34+
return cmpEqWith(comparing(compareFn.toFunction()), x, y);
3235
}
3336

3437
@Override
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.jnape.palatable.lambda.functions.builtin.fn3;
2+
3+
import com.jnape.palatable.lambda.functions.Fn3;
4+
import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
5+
import com.jnape.palatable.lambda.functions.specialized.Predicate;
6+
7+
import java.util.Comparator;
8+
9+
import static com.jnape.palatable.lambda.functions.builtin.fn3.Compare.compare;
10+
import static com.jnape.palatable.lambda.functions.ordering.ComparisonRelation.equal;
11+
import static com.jnape.palatable.lambda.functions.specialized.Predicate.predicate;
12+
13+
/**
14+
* Given a {@link Comparator} from some type <code>A</code> and two values of type <code>A</code>, return <code>true</code>
15+
* if the first value is strictly equal to the second value (according to {@link Comparator#compare(A, A)}
16+
* otherwise, return false.
17+
*
18+
* @param <A> the value type
19+
* @see CmpEqBy
20+
* @see LTBy
21+
* @see GTBy
22+
* @see Compare
23+
*/
24+
public final class CmpEqWith<A> implements Fn3<Comparator<A>, A, A, Boolean> {
25+
26+
private static final CmpEqWith<?> INSTANCE = new CmpEqWith<>();
27+
28+
private CmpEqWith() {
29+
}
30+
31+
@Override
32+
public BiPredicate<A, A> apply(Comparator<A> compareFn) {
33+
return Fn3.super.apply(compareFn)::apply;
34+
}
35+
36+
@Override
37+
public Predicate<A> apply(Comparator<A> compareFn, A x) {
38+
return predicate(Fn3.super.apply(compareFn, x));
39+
}
40+
41+
@SuppressWarnings("unchecked")
42+
public static <A> CmpEqWith<A> cmpEqWith() {
43+
return (CmpEqWith<A>) INSTANCE;
44+
}
45+
46+
public static <A> BiPredicate<A, A> cmpEqWith(Comparator<A> comparator) {
47+
return CmpEqWith.<A>cmpEqWith().apply(comparator);
48+
}
49+
50+
public static <A> Predicate<A> cmpEqWith(Comparator<A> comparator, A x) {
51+
return CmpEqWith.cmpEqWith(comparator).apply(x);
52+
}
53+
54+
public static <A> Boolean cmpEqWith(Comparator<A> comparator, A x, A y) {
55+
return cmpEqWith(comparator, x).apply(y);
56+
}
57+
58+
@Override
59+
public Boolean checkedApply(Comparator<A> comparator, A a, A a2) {
60+
return compare(comparator, a, a2).equals(equal());
61+
}
62+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.jnape.palatable.lambda.functions.builtin.fn3;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.lambda.functions.Fn2;
5+
import com.jnape.palatable.lambda.functions.Fn3;
6+
import com.jnape.palatable.lambda.functions.ordering.ComparisonRelation;
7+
8+
import java.util.Comparator;
9+
10+
/**
11+
* Given a {@link Comparator} from some type <code>A</code> and two values of type <code>A</code>, return a
12+
* {@link ComparisonRelation} of the first value with reference to the second value (according to {@link Comparator#compare(A, A)}.
13+
* The order of parameters is flipped with respect to {@link Comparator#compare(A, A)} for more idiomatic partial application.
14+
*
15+
* <p>
16+
* Example:
17+
* <pre>
18+
* {@code
19+
* Compare.compare(naturalOrder(), 1, 2); // ComparisonRelation.GreaterThan
20+
* Compare.compare(naturalOrder(), 2, 1); // ComparisonRelation.LessThan
21+
* Compare.compare(naturalOrder(), 1, 1); // ComparisonRelation.Equal
22+
* }
23+
* </pre>
24+
* </p>
25+
*
26+
* @param <A> the value type
27+
* @see Comparator
28+
* @see Compare
29+
*/
30+
public final class Compare<A> implements Fn3<Comparator<A>, A, A, ComparisonRelation> {
31+
private static final Compare<?> INSTANCE = new Compare<>();
32+
33+
private Compare() { }
34+
35+
@Override
36+
public ComparisonRelation checkedApply(Comparator<A> aComparator, A a, A a2) throws Throwable {
37+
return ComparisonRelation.fromInt(aComparator.compare(a2, a));
38+
}
39+
40+
@SuppressWarnings("unchecked")
41+
public static <A> Compare<A> compare() {
42+
return (Compare<A>) INSTANCE;
43+
}
44+
45+
public static <A> Fn2<A, A, ComparisonRelation> compare(Comparator<A> comparator) {
46+
return Compare.<A>compare().apply(comparator);
47+
}
48+
49+
public static <A> Fn1<A, ComparisonRelation> compare(Comparator<A> comparator, A a) {
50+
return compare(comparator).apply(a);
51+
}
52+
53+
public static <A> ComparisonRelation compare(Comparator<A> aComparator, A a, A a2) {
54+
return compare(aComparator, a).apply(a2);
55+
}
56+
}

src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTBy.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
77
import com.jnape.palatable.lambda.functions.specialized.Predicate;
88

9+
import static com.jnape.palatable.lambda.functions.builtin.fn3.GTWith.gtWith;
910
import static com.jnape.palatable.lambda.functions.specialized.Predicate.predicate;
11+
import static java.util.Comparator.comparing;
1012

1113
/**
1214
* Given a mapping function from some type <code>A</code> to some {@link Comparable} type <code>B</code> and two values
@@ -16,6 +18,7 @@
1618
* @param <A> the value type
1719
* @param <B> the mapped comparison type
1820
* @see GT
21+
* @see GTWith
1922
* @see LTBy
2023
*/
2124
public final class GTBy<A, B extends Comparable<B>> implements Fn3<Fn1<? super A, ? extends B>, A, A, Boolean> {
@@ -27,7 +30,7 @@ private GTBy() {
2730

2831
@Override
2932
public Boolean checkedApply(Fn1<? super A, ? extends B> compareFn, A y, A x) {
30-
return compareFn.apply(x).compareTo(compareFn.apply(y)) > 0;
33+
return gtWith(comparing(compareFn.toFunction()), y, x);
3134
}
3235

3336
@Override

src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTEBy.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
77
import com.jnape.palatable.lambda.functions.specialized.Predicate;
88

9-
import static com.jnape.palatable.lambda.functions.builtin.fn3.CmpEqBy.cmpEqBy;
9+
import static com.jnape.palatable.lambda.functions.builtin.fn3.GTEWith.gteWith;
1010
import static com.jnape.palatable.lambda.functions.specialized.Predicate.predicate;
11+
import static java.util.Comparator.comparing;
1112

1213
/**
1314
* Given a mapping function from some type <code>A</code> to some {@link Comparable} type <code>B</code> and two values
@@ -18,6 +19,7 @@
1819
* @param <A> the value type
1920
* @param <B> the mapped comparison type
2021
* @see GTE
22+
* @see GTEWith
2123
* @see LTEBy
2224
*/
2325
public final class GTEBy<A, B extends Comparable<B>> implements Fn3<Fn1<? super A, ? extends B>, A, A, Boolean> {
@@ -29,7 +31,7 @@ private GTEBy() {
2931

3032
@Override
3133
public Boolean checkedApply(Fn1<? super A, ? extends B> compareFn, A y, A x) {
32-
return GTBy.<A, B>gtBy(compareFn).or(cmpEqBy(compareFn)).apply(y, x);
34+
return gteWith(comparing(compareFn.toFunction()), y, x);
3335
}
3436

3537
@Override
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.jnape.palatable.lambda.functions.builtin.fn3;
2+
3+
import com.jnape.palatable.lambda.functions.Fn3;
4+
import com.jnape.palatable.lambda.functions.builtin.fn2.GTE;
5+
import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
6+
import com.jnape.palatable.lambda.functions.specialized.Predicate;
7+
8+
import java.util.Comparator;
9+
10+
import static com.jnape.palatable.lambda.functions.builtin.fn3.LTWith.ltWith;
11+
import static com.jnape.palatable.lambda.functions.specialized.Predicate.predicate;
12+
13+
/**
14+
* Given a {@link Comparator} from some type <code>A</code> and two values of type <code>A</code>,
15+
* return <code>true</code> if the second value is greater than or equal to the first value in
16+
* terms of their mapped <code>B</code> results according to {@link Comparator#compare(A, A)};
17+
* otherwise, return false.
18+
*
19+
* @param <A> the value type
20+
* @see GTE
21+
* @see GTEBy
22+
* @see LTEWith
23+
*/
24+
public final class GTEWith<A> implements Fn3<Comparator<A>, A, A, Boolean> {
25+
26+
private static final GTEWith<?> INSTANCE = new GTEWith<>();
27+
28+
private GTEWith() {
29+
}
30+
31+
@Override
32+
public BiPredicate<A, A> apply(Comparator<A> compareFn) {
33+
return Fn3.super.apply(compareFn)::apply;
34+
}
35+
36+
@Override
37+
public Predicate<A> apply(Comparator<A> compareFn, A x) {
38+
return predicate(Fn3.super.apply(compareFn, x));
39+
}
40+
41+
@SuppressWarnings("unchecked")
42+
public static <A> GTEWith<A> gteWith() {
43+
return (GTEWith<A>) INSTANCE;
44+
}
45+
46+
public static <A> BiPredicate<A, A> gteWith(Comparator<A> comparator) {
47+
return GTEWith.<A>gteWith().apply(comparator);
48+
}
49+
50+
public static <A> Predicate<A> gteWith(Comparator<A> comparator, A y) {
51+
return GTEWith.gteWith(comparator).apply(y);
52+
}
53+
54+
public static <A> Boolean gteWith(Comparator<A> comparator, A y, A x) {
55+
return gteWith(comparator, y).apply(x);
56+
}
57+
58+
@Override
59+
public Boolean checkedApply(Comparator<A> comparator, A a, A a2) {
60+
return !ltWith(comparator, a, a2);
61+
}
62+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.jnape.palatable.lambda.functions.builtin.fn3;
2+
3+
import com.jnape.palatable.lambda.functions.Fn3;
4+
import com.jnape.palatable.lambda.functions.builtin.fn2.GT;
5+
import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
6+
import com.jnape.palatable.lambda.functions.specialized.Predicate;
7+
8+
import java.util.Comparator;
9+
10+
import static com.jnape.palatable.lambda.functions.builtin.fn3.Compare.compare;
11+
import static com.jnape.palatable.lambda.functions.ordering.ComparisonRelation.greaterThan;
12+
import static com.jnape.palatable.lambda.functions.specialized.Predicate.predicate;
13+
14+
/**
15+
* Given a {@link Comparator} from some type <code>A</code> and two values of type <code>A</code>,
16+
* return <code>true</code> if the second value is strictly greater than the first value in
17+
* terms of their mapped <code>B</code> results; otherwise, return false.
18+
*
19+
* @param <A> the value type
20+
* @see GT
21+
* @see GTBy
22+
* @see LTWith
23+
*/
24+
public final class GTWith<A> implements Fn3<Comparator<A>, A, A, Boolean> {
25+
26+
private static final GTWith<?> INSTANCE = new GTWith<>();
27+
28+
private GTWith() {
29+
}
30+
31+
@Override
32+
public BiPredicate<A, A> apply(Comparator<A> compareFn) {
33+
return Fn3.super.apply(compareFn)::apply;
34+
}
35+
36+
@Override
37+
public Predicate<A> apply(Comparator<A> compareFn, A x) {
38+
return predicate(Fn3.super.apply(compareFn, x));
39+
}
40+
41+
@SuppressWarnings("unchecked")
42+
public static <A> GTWith<A> gtWith() {
43+
return (GTWith<A>) INSTANCE;
44+
}
45+
46+
public static <A> BiPredicate<A, A> gtWith(Comparator<A> comparator) {
47+
return GTWith.<A>gtWith().apply(comparator);
48+
}
49+
50+
public static <A> Predicate<A> gtWith(Comparator<A> comparator, A y) {
51+
return GTWith.gtWith(comparator).apply(y);
52+
}
53+
54+
public static <A> Boolean gtWith(Comparator<A> comparator, A y, A x) {
55+
return gtWith(comparator, y).apply(x);
56+
}
57+
58+
@Override
59+
public Boolean checkedApply(Comparator<A> comparator, A a, A a2) {
60+
return compare(comparator, a, a2).equals(greaterThan());
61+
}
62+
}

src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTBy.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
77
import com.jnape.palatable.lambda.functions.specialized.Predicate;
88

9+
import static com.jnape.palatable.lambda.functions.builtin.fn3.LTWith.ltWith;
910
import static com.jnape.palatable.lambda.functions.specialized.Predicate.predicate;
11+
import static java.util.Comparator.comparing;
1012

1113
/**
1214
* Given a mapping function from some type <code>A</code> to some {@link Comparable} type <code>B</code> and two values
@@ -27,7 +29,7 @@ private LTBy() {
2729

2830
@Override
2931
public Boolean checkedApply(Fn1<? super A, ? extends B> compareFn, A y, A x) {
30-
return compareFn.apply(x).compareTo(compareFn.apply(y)) < 0;
32+
return ltWith(comparing(compareFn.toFunction()), y, x);
3133
}
3234

3335
@Override

src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEBy.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
77
import com.jnape.palatable.lambda.functions.specialized.Predicate;
88

9-
import static com.jnape.palatable.lambda.functions.builtin.fn3.CmpEqBy.cmpEqBy;
9+
import static com.jnape.palatable.lambda.functions.builtin.fn3.LTEWith.lteWith;
10+
import static java.util.Comparator.comparing;
1011

1112
/**
1213
* Given a mapping function from some type <code>A</code> to some {@link Comparable} type <code>B</code> and two values
@@ -28,7 +29,7 @@ private LTEBy() {
2829

2930
@Override
3031
public Boolean checkedApply(Fn1<? super A, ? extends B> compareFn, A y, A x) {
31-
return LTBy.<A, B>ltBy(compareFn).or(cmpEqBy(compareFn)).apply(y, x);
32+
return lteWith(comparing(compareFn.toFunction()), y, x);
3233
}
3334

3435
@Override

0 commit comments

Comments
 (0)