From 934fe9212da4cbeb35536083a3184029891bf09e Mon Sep 17 00:00:00 2001 From: haojin <2678432321@qq.com> Date: Fri, 23 Apr 2021 22:41:17 +0800 Subject: [PATCH 1/5] Implement shortcut for 0.0 and 1.0 percentile calculations, and add two new tests --- .../src/main/java/org/jooq/lambda/Agg.java | 17 +- .../java/org/jooq/lambda/CollectorTests.java | 147 ++++++++++++++++++ jOOL/src/main/java/org/jooq/lambda/Agg.java | 17 +- .../java/org/jooq/lambda/CollectorTests.java | 147 ++++++++++++++++++ 4 files changed, 318 insertions(+), 10 deletions(-) diff --git a/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java b/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java index ebd6e0e9..2a06246f 100644 --- a/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java +++ b/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java @@ -911,6 +911,18 @@ else if (l1[0] == null) if (percentile < 0.0 || percentile > 1.0) throw new IllegalArgumentException("Percentile must be between 0.0 and 1.0"); + // CS304 Issue link: https://github.com/jOOQ/jOOL/issues/376 + if (percentile == 0.0) + // If percentile is 0, this is the same as taking the item with the minimum value. + return minBy(function, comparator); + else if (percentile == 1.0) + // If percentile is 1, this is the same as taking the item with the maximum value, + // If there are multiple maxima, take the last one. + return maxBy(function, (o1, o2) -> { + int compareResult = comparator.compare(o1, o2); + return compareResult == 0 ? -1 : compareResult; + }); + // At a later stage, we'll optimise this implementation in case that function is the identity function return Collector.of( () -> new ArrayList>(), @@ -929,11 +941,6 @@ else if (size == 1) l.sort(Comparator.comparing(t -> t.v2, comparator)); - if (percentile == 0.0) - return Optional.of(l.get(0).v1); - else if (percentile == 1.0) - return Optional.of(l.get(size - 1).v1); - // x.5 should be rounded down return Optional.of(l.get((int) -Math.round(-(size * percentile + 0.5)) - 1).v1); } diff --git a/jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java b/jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java index 815ec94e..636dbae4 100644 --- a/jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java +++ b/jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java @@ -307,6 +307,153 @@ public void testPercentileWithStringsAndFunction() { Utils.assertThrows(IllegalArgumentException.class, () -> Stream.of("a").collect(percentileBy(-1, String::length))); Utils.assertThrows(IllegalArgumentException.class, () -> Stream.of("a").collect(percentileBy(2, String::length))); } + + @Test + public void testPercentileWithStringsAndFunctionWithDifferentValues() { + + // CS304 (manually written) Issue link: https://github.com/jOOQ/jOOL/issues/376 + // In the test testPercentileWithStringsAndFunction, the values (length) of the items are all the same, + // The function used in this test will take the first character of each string to be compared. + Function getFirstLetter = s -> s.length() == 0 ? 0 : s.charAt(0); + + // Min + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.0, getFirstLetter))); + + // 0.25 percentile + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.25, getFirstLetter))); + + // Median + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.5, getFirstLetter))); + + // 0.75 percentile + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("t"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.75, getFirstLetter))); + + // Max + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("t"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("u"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("v"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(1.0, getFirstLetter))); + } + + @Test + public void testPercentileWithStringsAndFunctionWithDifferentValues2() { + + // CS304 (manually written) Issue link: https://github.com/jOOQ/jOOL/issues/376 + // The function used in this test will take the minus value of the first character of each string to be compared. + Function getMinusValueOfFirstLetter = s -> s.length() == 0 ? 0 : (int) -s.charAt(0); + + // Min + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("t"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("u"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("v"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + + // 0.25 + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("t"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + + // 0.5 + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + + // 0.75 + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + + // Max + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + } @Test public void testRank() { diff --git a/jOOL/src/main/java/org/jooq/lambda/Agg.java b/jOOL/src/main/java/org/jooq/lambda/Agg.java index ebd6e0e9..2a06246f 100644 --- a/jOOL/src/main/java/org/jooq/lambda/Agg.java +++ b/jOOL/src/main/java/org/jooq/lambda/Agg.java @@ -911,6 +911,18 @@ else if (l1[0] == null) if (percentile < 0.0 || percentile > 1.0) throw new IllegalArgumentException("Percentile must be between 0.0 and 1.0"); + // CS304 Issue link: https://github.com/jOOQ/jOOL/issues/376 + if (percentile == 0.0) + // If percentile is 0, this is the same as taking the item with the minimum value. + return minBy(function, comparator); + else if (percentile == 1.0) + // If percentile is 1, this is the same as taking the item with the maximum value, + // If there are multiple maxima, take the last one. + return maxBy(function, (o1, o2) -> { + int compareResult = comparator.compare(o1, o2); + return compareResult == 0 ? -1 : compareResult; + }); + // At a later stage, we'll optimise this implementation in case that function is the identity function return Collector.of( () -> new ArrayList>(), @@ -929,11 +941,6 @@ else if (size == 1) l.sort(Comparator.comparing(t -> t.v2, comparator)); - if (percentile == 0.0) - return Optional.of(l.get(0).v1); - else if (percentile == 1.0) - return Optional.of(l.get(size - 1).v1); - // x.5 should be rounded down return Optional.of(l.get((int) -Math.round(-(size * percentile + 0.5)) - 1).v1); } diff --git a/jOOL/src/test/java/org/jooq/lambda/CollectorTests.java b/jOOL/src/test/java/org/jooq/lambda/CollectorTests.java index 815ec94e..636dbae4 100644 --- a/jOOL/src/test/java/org/jooq/lambda/CollectorTests.java +++ b/jOOL/src/test/java/org/jooq/lambda/CollectorTests.java @@ -307,6 +307,153 @@ public void testPercentileWithStringsAndFunction() { Utils.assertThrows(IllegalArgumentException.class, () -> Stream.of("a").collect(percentileBy(-1, String::length))); Utils.assertThrows(IllegalArgumentException.class, () -> Stream.of("a").collect(percentileBy(2, String::length))); } + + @Test + public void testPercentileWithStringsAndFunctionWithDifferentValues() { + + // CS304 (manually written) Issue link: https://github.com/jOOQ/jOOL/issues/376 + // In the test testPercentileWithStringsAndFunction, the values (length) of the items are all the same, + // The function used in this test will take the first character of each string to be compared. + Function getFirstLetter = s -> s.length() == 0 ? 0 : s.charAt(0); + + // Min + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.0, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.0, getFirstLetter))); + + // 0.25 percentile + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.25, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.25, getFirstLetter))); + + // Median + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.5, getFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.5, getFirstLetter))); + + // 0.75 percentile + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.75, getFirstLetter))); + assertEquals(Optional.of("t"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.75, getFirstLetter))); + + // Max + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("t"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("u"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(1.0, getFirstLetter))); + assertEquals(Optional.of("v"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(1.0, getFirstLetter))); + } + + @Test + public void testPercentileWithStringsAndFunctionWithDifferentValues2() { + + // CS304 (manually written) Issue link: https://github.com/jOOQ/jOOL/issues/376 + // The function used in this test will take the minus value of the first character of each string to be compared. + Function getMinusValueOfFirstLetter = s -> s.length() == 0 ? 0 : (int) -s.charAt(0); + + // Min + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("t"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("u"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("v"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.0, getMinusValueOfFirstLetter))); + + // 0.25 + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("i"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("j"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("t"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.25, getMinusValueOfFirstLetter))); + + // 0.5 + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("d"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.5, getMinusValueOfFirstLetter))); + + // 0.75 + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("b"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("c"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(0.75, getMinusValueOfFirstLetter))); + + // Max + assertEquals(Optional.of("a"), Stream.of("a").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + assertEquals(Optional.of("a"), Stream.of("a", "b", "c", "d", "j", "i", "c", "c", "t", "u", "v").collect(percentileBy(1.0, getMinusValueOfFirstLetter))); + } @Test public void testRank() { From 8fd0eee5db33cd93516b8e590322a8eb5629ac52 Mon Sep 17 00:00:00 2001 From: haojin <2678432321@qq.com> Date: Fri, 23 Apr 2021 22:56:20 +0800 Subject: [PATCH 2/5] Implement shortcut for 0.0 and 1.0 percentile calculations, and add two new tests --- jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java | 1 + jOOL/src/test/java/org/jooq/lambda/CollectorTests.java | 1 + 2 files changed, 2 insertions(+) diff --git a/jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java b/jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java index 636dbae4..b79fc4ef 100644 --- a/jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java +++ b/jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java @@ -36,6 +36,7 @@ import java.util.Optional; import java.util.stream.Collector; import java.util.stream.Stream; +import java.util.function.Function; import org.jooq.lambda.tuple.Tuple; import org.jooq.lambda.tuple.Tuple9; diff --git a/jOOL/src/test/java/org/jooq/lambda/CollectorTests.java b/jOOL/src/test/java/org/jooq/lambda/CollectorTests.java index 636dbae4..b79fc4ef 100644 --- a/jOOL/src/test/java/org/jooq/lambda/CollectorTests.java +++ b/jOOL/src/test/java/org/jooq/lambda/CollectorTests.java @@ -36,6 +36,7 @@ import java.util.Optional; import java.util.stream.Collector; import java.util.stream.Stream; +import java.util.function.Function; import org.jooq.lambda.tuple.Tuple; import org.jooq.lambda.tuple.Tuple9; From dabfeafa4f94e78c31395331b0b0e936eeec2e49 Mon Sep 17 00:00:00 2001 From: haojin <2678432321@qq.com> Date: Fri, 23 Apr 2021 23:06:02 +0800 Subject: [PATCH 3/5] Modify the javadoc for the function PERCENTILEBY --- jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java | 2 +- jOOL/src/main/java/org/jooq/lambda/Agg.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java b/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java index 2a06246f..90fa6cfb 100644 --- a/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java +++ b/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java @@ -905,7 +905,7 @@ else if (l1[0] == null) } /** - * Get a {@link Collector} that calculates the derived PERCENTILE_DISC(percentile) function given a specific ordering. + * Get a {@link Collector} that calculates the derived PERCENTILE_DISC(percentile) function given a specific ordering or the ordering of the index. */ public static Collector> percentileBy(double percentile, Function function, Comparator comparator) { if (percentile < 0.0 || percentile > 1.0) diff --git a/jOOL/src/main/java/org/jooq/lambda/Agg.java b/jOOL/src/main/java/org/jooq/lambda/Agg.java index 2a06246f..90fa6cfb 100644 --- a/jOOL/src/main/java/org/jooq/lambda/Agg.java +++ b/jOOL/src/main/java/org/jooq/lambda/Agg.java @@ -905,7 +905,7 @@ else if (l1[0] == null) } /** - * Get a {@link Collector} that calculates the derived PERCENTILE_DISC(percentile) function given a specific ordering. + * Get a {@link Collector} that calculates the derived PERCENTILE_DISC(percentile) function given a specific ordering or the ordering of the index. */ public static Collector> percentileBy(double percentile, Function function, Comparator comparator) { if (percentile < 0.0 || percentile > 1.0) From d3b7bce2f00b661afd98551da39a41d7151062cb Mon Sep 17 00:00:00 2001 From: Hammer_Zhang <49118946+JingHuaMan@users.noreply.github.com> Date: Sun, 25 Apr 2021 22:17:07 +0800 Subject: [PATCH 4/5] Modify javadoc for PERCENTILEBY --- jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java b/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java index 90fa6cfb..8c0a5e23 100644 --- a/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java +++ b/jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java @@ -905,7 +905,11 @@ else if (l1[0] == null) } /** - * Get a {@link Collector} that calculates the derived PERCENTILE_DISC(percentile) function given a specific ordering or the ordering of the index. + * Get a {@link Collector} that calculates the derived PERCENTILE_DISC(percentile) function given a specific ordering. + * + * @param function map the items in the streams into values + * @param comparator comparator used for sorting the items + * @return a collector that calculates the derived PERCENTILE_DISC(percentile) function */ public static Collector> percentileBy(double percentile, Function function, Comparator comparator) { if (percentile < 0.0 || percentile > 1.0) From 7a4a5cdcebcf44fbbb09babf08a11a780018f229 Mon Sep 17 00:00:00 2001 From: Hammer_Zhang <49118946+JingHuaMan@users.noreply.github.com> Date: Sun, 25 Apr 2021 22:18:40 +0800 Subject: [PATCH 5/5] Modify javadoc for PERCENTILEBY --- jOOL/src/main/java/org/jooq/lambda/Agg.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jOOL/src/main/java/org/jooq/lambda/Agg.java b/jOOL/src/main/java/org/jooq/lambda/Agg.java index 90fa6cfb..8c0a5e23 100644 --- a/jOOL/src/main/java/org/jooq/lambda/Agg.java +++ b/jOOL/src/main/java/org/jooq/lambda/Agg.java @@ -905,7 +905,11 @@ else if (l1[0] == null) } /** - * Get a {@link Collector} that calculates the derived PERCENTILE_DISC(percentile) function given a specific ordering or the ordering of the index. + * Get a {@link Collector} that calculates the derived PERCENTILE_DISC(percentile) function given a specific ordering. + * + * @param function map the items in the streams into values + * @param comparator comparator used for sorting the items + * @return a collector that calculates the derived PERCENTILE_DISC(percentile) function */ public static Collector> percentileBy(double percentile, Function function, Comparator comparator) { if (percentile < 0.0 || percentile > 1.0)