From fd127fcb0de2004d1908af21bbc131b5982dc5b6 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Mon, 8 Jun 2020 19:10:28 +0300 Subject: [PATCH 01/29] Define all signatures toMap methods --- .../one/util/streamex/MoreCollectors.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 3d4746e1..11a93ab9 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -34,6 +34,7 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.Set; +import java.util.concurrent.ConcurrentMap; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BiPredicate; @@ -168,6 +169,61 @@ private MoreCollectors() { }, Function.identity(), set -> set.size() == size, UNORDERED_ID_CHARACTERISTICS); } + + public static Collector, ?, Map> toMap() { + return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue); + } + + public static Collector, ?, ConcurrentMap> toConcurrentMap() { + return Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue); + } + + public static Collector, ?, Map> toMap( + BinaryOperator combiner) { + + return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, combiner); + } + + public static Collector, ?, Map> toMap( + Function valueMapper) { + + return null; + } + + public static Collector, ?, Map> toMap( + Function valueMapper, BinaryOperator combiner) { + + Objects.requireNonNull(valueMapper); + return null; + } + + public static > Collector, ?, M> toCustomMap( + Supplier mapSupplier) { + + return null; + } + + public static > Collector, ?, M> toCustomMap( + Function valueMapper, Supplier mapSupplier) { + + Objects.requireNonNull(valueMapper); + return null; + } + + public static > Collector, ?, M> toCustomMap( + BinaryOperator combiner, Supplier mapSupplier) { + + return null; + } + + public static > Collector, ?, M> toCustomMap( + Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { + + Objects.requireNonNull(valueMapper); + return null; + } + + /** * Returns a {@code Collector} which counts a number of distinct values the * mapper function returns for the stream elements. From d48db2ada5c4c63c511e28e5cbd92f14ecf27b62 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Mon, 8 Jun 2020 19:11:27 +0300 Subject: [PATCH 02/29] Add basic test for ToMap without parameters --- .../one/util/streamex/MoreCollectorsTest.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 36ad9d20..8a1b0ab0 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -33,6 +33,8 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -588,6 +590,65 @@ public void testToEnumSet() { checkCollectorEmpty("Empty", EnumSet.noneOf(TimeUnit.class), MoreCollectors.toEnumSet(TimeUnit.class)); } + @Test + public void testToMap() { + assertThrows(IllegalStateException.class, () -> + EntryStream.generate(() -> "a", () -> 1).limit(10).collect(MoreCollectors.toMap())); + + assertThrows(NullPointerException.class, () -> MoreCollectors.toMap(null, null)); + + { + Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****") + .collect(MoreCollectors.toMap()); + checkCollector("toMap", expected, expected.entrySet()::stream, MoreCollectors.toMap()); + } + + final Map expected = new HashMap<>(); + expected.put(1, "one"); + expected.put(2, "two"); + expected.put(3, "three"); + expected.put(4, "four"); + expected.put(5, "five"); + + checkCollector("toMap", expected, expected.entrySet()::stream, MoreCollectors.toMap()); + streamEx(expected.entrySet()::stream, supplier -> { + Map result = supplier.get().collect(MoreCollectors.toMap()); + assertEquals("one", result.get(1)); + assertEquals("two", result.get(2)); + assertEquals("three", result.get(3)); + assertEquals("four", result.get(4)); + assertEquals("five", result.get(5)); + }); + + checkCollectorEmpty("Empty", Collections.emptyMap(), MoreCollectors.toMap()); + + /*streamEx(EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****")::stream, supplier -> { + Map result = supplier.get().collect(MoreCollectors.toMap()); + assertEquals("*", result.get(1)); + assertEquals("**", result.get(2)); + assertEquals("***", result.get(3)); + assertEquals("****", result.get(4)); + });*/ + } + + @Test + public void toConcurrentMap() { + final ConcurrentMap expected = new ConcurrentHashMap<>(); + expected.put(0, "zero"); + expected.put(1, "one"); + expected.put(2, "two"); + expected.put(3, "three"); + expected.put(4, "four"); + expected.put(5, "five"); + expected.put(6, "six"); + expected.put(7, "seven"); + expected.put(8, "eight"); + expected.put(9, "nine"); + expected.put(10, "ten"); + checkCollector("toConcurrentMap", expected, expected.entrySet()::stream, + MoreCollectors.toConcurrentMap()); + } + @Test public void testFlatMapping() { assertThrows(NullPointerException.class, () -> MoreCollectors.flatMapping(null)); From bd412ce76b70c20dd1cf30bffe3b2282ade550d1 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Tue, 9 Jun 2020 19:11:41 +0300 Subject: [PATCH 03/29] squash! Define all shortcut signatures --- .../one/util/streamex/MoreCollectors.java | 21 +++---- .../one/util/streamex/MoreCollectorsTest.java | 57 +++---------------- 2 files changed, 18 insertions(+), 60 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 11a93ab9..14dccddc 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -170,53 +170,50 @@ private MoreCollectors() { } - public static Collector, ?, Map> toMap() { + public static Collector, ?, Map> entriesToMap() { return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue); } - public static Collector, ?, ConcurrentMap> toConcurrentMap() { - return Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue); - } - - public static Collector, ?, Map> toMap( + public static Collector, ?, Map> entriesToMap( BinaryOperator combiner) { return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, combiner); } - public static Collector, ?, Map> toMap( + public static Collector, ?, Map> entriesToMap( Function valueMapper) { return null; } - public static Collector, ?, Map> toMap( + public static Collector, ?, Map> entriesToMap( Function valueMapper, BinaryOperator combiner) { Objects.requireNonNull(valueMapper); return null; } - public static > Collector, ?, M> toCustomMap( + public static > Collector, ?, M> entriesToCustomMap( Supplier mapSupplier) { return null; } - public static > Collector, ?, M> toCustomMap( + public static > Collector, ?, M> entriesToCustomMap( + Function valueMapper, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); return null; } - public static > Collector, ?, M> toCustomMap( + public static > Collector, ?, M> entriesToCustomMap( BinaryOperator combiner, Supplier mapSupplier) { return null; } - public static > Collector, ?, M> toCustomMap( + public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 8a1b0ab0..8520689a 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -33,8 +33,6 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -591,62 +589,25 @@ public void testToEnumSet() { } @Test - public void testToMap() { + public void testEntriesToMap() { assertThrows(IllegalStateException.class, () -> - EntryStream.generate(() -> "a", () -> 1).limit(10).collect(MoreCollectors.toMap())); + EntryStream.generate(() -> "a", () -> 1).limit(10).collect(MoreCollectors.entriesToMap())); - assertThrows(NullPointerException.class, () -> MoreCollectors.toMap(null, null)); + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(null, null)); - { - Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****") - .collect(MoreCollectors.toMap()); - checkCollector("toMap", expected, expected.entrySet()::stream, MoreCollectors.toMap()); - } + checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToMap()); - final Map expected = new HashMap<>(); - expected.put(1, "one"); - expected.put(2, "two"); - expected.put(3, "three"); - expected.put(4, "four"); - expected.put(5, "five"); + Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****", 5, "*****").toMap(); - checkCollector("toMap", expected, expected.entrySet()::stream, MoreCollectors.toMap()); + checkCollector("entriesToMap", expected, expected.entrySet()::stream, MoreCollectors.entriesToMap()); streamEx(expected.entrySet()::stream, supplier -> { - Map result = supplier.get().collect(MoreCollectors.toMap()); - assertEquals("one", result.get(1)); - assertEquals("two", result.get(2)); - assertEquals("three", result.get(3)); - assertEquals("four", result.get(4)); - assertEquals("five", result.get(5)); - }); - - checkCollectorEmpty("Empty", Collections.emptyMap(), MoreCollectors.toMap()); - - /*streamEx(EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****")::stream, supplier -> { - Map result = supplier.get().collect(MoreCollectors.toMap()); + Map result = supplier.get().collect(MoreCollectors.entriesToMap()); assertEquals("*", result.get(1)); assertEquals("**", result.get(2)); assertEquals("***", result.get(3)); assertEquals("****", result.get(4)); - });*/ - } - - @Test - public void toConcurrentMap() { - final ConcurrentMap expected = new ConcurrentHashMap<>(); - expected.put(0, "zero"); - expected.put(1, "one"); - expected.put(2, "two"); - expected.put(3, "three"); - expected.put(4, "four"); - expected.put(5, "five"); - expected.put(6, "six"); - expected.put(7, "seven"); - expected.put(8, "eight"); - expected.put(9, "nine"); - expected.put(10, "ten"); - checkCollector("toConcurrentMap", expected, expected.entrySet()::stream, - MoreCollectors.toConcurrentMap()); + assertEquals("*****", result.get(5)); + }); } @Test From afbc8a9a7c3e7c3aa52479696bbf49143b84e041 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Wed, 10 Jun 2020 00:46:59 +0300 Subject: [PATCH 04/29] Test entitiesToMap with consumer --- .../one/util/streamex/MoreCollectorsTest.java | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 8520689a..ebc9ddf6 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -597,16 +597,49 @@ public void testEntriesToMap() { checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToMap()); - Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****", 5, "*****").toMap(); + { + Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****", 5, "*****").toMap(); + Supplier>> stream = expected.entrySet()::stream; + checkCollector("entriesToMap", expected, stream, MoreCollectors.entriesToMap()); + + streamEx(stream, supplier -> { + Map result = supplier.get().collect(MoreCollectors.entriesToMap()); + assertEquals("*", result.get(1)); + assertEquals("**", result.get(2)); + assertEquals("***", result.get(3)); + assertEquals("****", result.get(4)); + assertEquals("*****", result.get(5)); + }); + } + } - checkCollector("entriesToMap", expected, expected.entrySet()::stream, MoreCollectors.entriesToMap()); - streamEx(expected.entrySet()::stream, supplier -> { - Map result = supplier.get().collect(MoreCollectors.entriesToMap()); - assertEquals("*", result.get(1)); - assertEquals("**", result.get(2)); + @Test + public void testEntriesToMapWithCombiner() { + streamEx(() -> Stream.of( + EntryStream.of(1, "*").toMap(), + EntryStream.of(1, "*", 2, "*").toMap(), + EntryStream.of(1, "*", 2, "*", 3, "*").toMap(), + EntryStream.of(1, "*", 2, "*", 3, "*", 4, "*").toMap(), + EntryStream.of(1, "*", 2, "*", 3, "*", 4, "*", 5, "*").toMap()) + .flatMap(map -> map.entrySet().stream()), supplier -> { + Map result = supplier.get().collect(MoreCollectors.entriesToMap(String::concat)); + assertEquals("*****", result.get(1)); + assertEquals("****", result.get(2)); assertEquals("***", result.get(3)); - assertEquals("****", result.get(4)); - assertEquals("*****", result.get(5)); + assertEquals("**", result.get(4)); + assertEquals("*", result.get(5)); + }); + + streamEx(() -> Stream.of( + EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four").toMap(), + EntryStream.of(1, "ein", 2, "zwei", 3, "drei").toMap(), + EntryStream.of(1, "une", 2, "deux").toMap()) + .flatMap(map -> map.entrySet().stream()), supplier -> { + Map result = supplier.get().collect(MoreCollectors.entriesToMap((left, right) -> left + "," + right)); + assertEquals("one,ein,une", result.get(1)); + assertEquals("two,zwei,deux", result.get(2)); + assertEquals("three,drei", result.get(3)); + assertEquals("four", result.get(4)); }); } From 424a1489f05d724da35881c44d4453043cd27ec7 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Wed, 10 Jun 2020 19:28:29 +0300 Subject: [PATCH 05/29] Implement all entriesToMap and entriesToCustomMap methods --- .../one/util/streamex/MoreCollectors.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 14dccddc..77b5ecc2 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -34,7 +34,6 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.Set; -import java.util.concurrent.ConcurrentMap; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BiPredicate; @@ -171,55 +170,53 @@ private MoreCollectors() { public static Collector, ?, Map> entriesToMap() { - return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue); + return Collectors.toMap(Entry::getKey, Entry::getValue); } public static Collector, ?, Map> entriesToMap( BinaryOperator combiner) { - - return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, combiner); + return Collectors.toMap(Entry::getKey, Entry::getValue, combiner); } public static Collector, ?, Map> entriesToMap( Function valueMapper) { - - return null; + return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue())); } public static Collector, ?, Map> entriesToMap( Function valueMapper, BinaryOperator combiner) { - Objects.requireNonNull(valueMapper); - return null; + return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), combiner); } public static > Collector, ?, M> entriesToCustomMap( Supplier mapSupplier) { - - return null; + return Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), mapSupplier); } public static > Collector, ?, M> entriesToCustomMap( - Function valueMapper, Supplier mapSupplier) { - Objects.requireNonNull(valueMapper); - return null; + return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), throwingMerger(), mapSupplier); } public static > Collector, ?, M> entriesToCustomMap( BinaryOperator combiner, Supplier mapSupplier) { - - return null; + return Collectors.toMap(Entry::getKey, Entry::getValue, combiner, mapSupplier); } public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); - return null; + return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), combiner, mapSupplier); } + private static BinaryOperator throwingMerger() { + return (firstKey, secondKey) -> { + throw new IllegalStateException("Duplicate entry keys are not allowed (attempt to merge key '" + firstKey + "'). "); + }; + } /** * Returns a {@code Collector} which counts a number of distinct values the From 0125df9369768d94989bf5ada4539a0b824a43d1 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Wed, 10 Jun 2020 19:35:29 +0300 Subject: [PATCH 06/29] Implement all entriesToMap and entriesToCustomMap methods --- .../java/one/util/streamex/MoreCollectorsTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index ebc9ddf6..550d5bc0 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -643,6 +643,18 @@ public void testEntriesToMapWithCombiner() { }); } + @Test + public void testEntriesToMapWithValueMapper() { + streamEx(() -> EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), + supplier -> { + Map result = supplier.get().collect(MoreCollectors.entriesToMap((value) -> "See #" + value)); + assertEquals("See #one", result.get(1)); + assertEquals("See #two", result.get(2)); + assertEquals("See #three", result.get(3)); + assertEquals("See #four", result.get(4)); + }); + } + @Test public void testFlatMapping() { assertThrows(NullPointerException.class, () -> MoreCollectors.flatMapping(null)); From 382e4fa608b7b721f6cb18c652cce43c6ea33164 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Thu, 11 Jun 2020 10:37:59 +0300 Subject: [PATCH 07/29] Improve formatting for new signatures --- src/main/java/one/util/streamex/MoreCollectors.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 77b5ecc2..71217ec6 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -168,18 +168,15 @@ private MoreCollectors() { }, Function.identity(), set -> set.size() == size, UNORDERED_ID_CHARACTERISTICS); } - public static Collector, ?, Map> entriesToMap() { return Collectors.toMap(Entry::getKey, Entry::getValue); } - public static Collector, ?, Map> entriesToMap( - BinaryOperator combiner) { + public static Collector, ?, Map> entriesToMap(BinaryOperator combiner) { return Collectors.toMap(Entry::getKey, Entry::getValue, combiner); } - public static Collector, ?, Map> entriesToMap( - Function valueMapper) { + public static Collector, ?, Map> entriesToMap(Function valueMapper) { return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue())); } @@ -207,7 +204,6 @@ private MoreCollectors() { public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { - Objects.requireNonNull(valueMapper); return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), combiner, mapSupplier); } From cd58d2023f8c704f080bcd212db16be0cb991da6 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Thu, 11 Jun 2020 10:38:04 +0300 Subject: [PATCH 08/29] Test entriesToMap with value mapper and combiner --- .../one/util/streamex/MoreCollectorsTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 550d5bc0..2e9fd90c 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -33,6 +33,7 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -655,6 +656,22 @@ public void testEntriesToMapWithValueMapper() { }); } + @Test + public void testEntriesToMapWithValueMapperAndCombiner() { + streamEx(() -> Stream.of( + EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four").toMap(), + EntryStream.of(1, "ein", 2, "zwei", 3, "drei").toMap(), + EntryStream.of(1, "une", 2, "deux").toMap()) + .flatMap(map -> map.entrySet().stream()), supplier -> { + Map result = supplier.get().collect( + MoreCollectors.entriesToMap((value) -> "['" + value + "']", (left, right) -> left + ", " + right)); + assertEquals("['one'], ['ein'], ['une']", result.get(1)); + assertEquals("['two'], ['zwei'], ['deux']", result.get(2)); + assertEquals("['three'], ['drei']", result.get(3)); + assertEquals("['four']", result.get(4)); + }); + } + @Test public void testFlatMapping() { assertThrows(NullPointerException.class, () -> MoreCollectors.flatMapping(null)); From 70889f47b5e5d9e9f334f1ad2902d76843909dc3 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Thu, 11 Jun 2020 11:03:48 +0300 Subject: [PATCH 09/29] Extend test entriesToMap with value mapper --- .../java/one/util/streamex/MoreCollectorsTest.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 2e9fd90c..12e1c5da 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -33,7 +33,6 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -654,6 +653,18 @@ public void testEntriesToMapWithValueMapper() { assertEquals("See #three", result.get(3)); assertEquals("See #four", result.get(4)); }); + + streamEx(() -> StreamEx.of("Bran Stark", "Arya Stark", "Jon Snow", "Tyrion (The Imp) Lannister", "Theon Greyjoy", + "Ser Jaime (The Kingslayer) Lannister", "Daenerys Stormborn Targaryen", "Khal Drogo", "Ser Jorah Mormont") + .mapToEntry(name -> name.contains("Khal") || name.contains("Ser")), supplier -> { + Map result = supplier.get().collect( + MoreCollectors.entriesToMap((value) -> { + return value ? "This character has celebrity title" : "Standard character"; + })); + assertEquals("This character has celebrity title", result.get("Khal Drogo")); + assertEquals("Standard character", result.get("Jon Snow")); + assertEquals("This character has celebrity title", result.get("Ser Jorah Mormont")); + }); } @Test From ed4606c97f2dcfd533e56f2ae75686571e9ccef8 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Mon, 8 Jun 2020 19:10:28 +0300 Subject: [PATCH 10/29] Define all signatures toMap methods --- .../one/util/streamex/MoreCollectors.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 3d4746e1..11a93ab9 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -34,6 +34,7 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.Set; +import java.util.concurrent.ConcurrentMap; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BiPredicate; @@ -168,6 +169,61 @@ private MoreCollectors() { }, Function.identity(), set -> set.size() == size, UNORDERED_ID_CHARACTERISTICS); } + + public static Collector, ?, Map> toMap() { + return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue); + } + + public static Collector, ?, ConcurrentMap> toConcurrentMap() { + return Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue); + } + + public static Collector, ?, Map> toMap( + BinaryOperator combiner) { + + return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, combiner); + } + + public static Collector, ?, Map> toMap( + Function valueMapper) { + + return null; + } + + public static Collector, ?, Map> toMap( + Function valueMapper, BinaryOperator combiner) { + + Objects.requireNonNull(valueMapper); + return null; + } + + public static > Collector, ?, M> toCustomMap( + Supplier mapSupplier) { + + return null; + } + + public static > Collector, ?, M> toCustomMap( + Function valueMapper, Supplier mapSupplier) { + + Objects.requireNonNull(valueMapper); + return null; + } + + public static > Collector, ?, M> toCustomMap( + BinaryOperator combiner, Supplier mapSupplier) { + + return null; + } + + public static > Collector, ?, M> toCustomMap( + Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { + + Objects.requireNonNull(valueMapper); + return null; + } + + /** * Returns a {@code Collector} which counts a number of distinct values the * mapper function returns for the stream elements. From b4d71afca49cb493df6f15f10cfc8327f00ba744 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Mon, 8 Jun 2020 19:11:27 +0300 Subject: [PATCH 11/29] Add basic test for ToMap without parameters --- .../one/util/streamex/MoreCollectorsTest.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index bc12dc00..869090ed 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -33,6 +33,8 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -591,6 +593,65 @@ public void testToEnumSet() { checkCollectorEmpty("Empty", EnumSet.noneOf(TimeUnit.class), MoreCollectors.toEnumSet(TimeUnit.class)); } + @Test + public void testToMap() { + assertThrows(IllegalStateException.class, () -> + EntryStream.generate(() -> "a", () -> 1).limit(10).collect(MoreCollectors.toMap())); + + assertThrows(NullPointerException.class, () -> MoreCollectors.toMap(null, null)); + + { + Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****") + .collect(MoreCollectors.toMap()); + checkCollector("toMap", expected, expected.entrySet()::stream, MoreCollectors.toMap()); + } + + final Map expected = new HashMap<>(); + expected.put(1, "one"); + expected.put(2, "two"); + expected.put(3, "three"); + expected.put(4, "four"); + expected.put(5, "five"); + + checkCollector("toMap", expected, expected.entrySet()::stream, MoreCollectors.toMap()); + streamEx(expected.entrySet()::stream, supplier -> { + Map result = supplier.get().collect(MoreCollectors.toMap()); + assertEquals("one", result.get(1)); + assertEquals("two", result.get(2)); + assertEquals("three", result.get(3)); + assertEquals("four", result.get(4)); + assertEquals("five", result.get(5)); + }); + + checkCollectorEmpty("Empty", Collections.emptyMap(), MoreCollectors.toMap()); + + /*streamEx(EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****")::stream, supplier -> { + Map result = supplier.get().collect(MoreCollectors.toMap()); + assertEquals("*", result.get(1)); + assertEquals("**", result.get(2)); + assertEquals("***", result.get(3)); + assertEquals("****", result.get(4)); + });*/ + } + + @Test + public void toConcurrentMap() { + final ConcurrentMap expected = new ConcurrentHashMap<>(); + expected.put(0, "zero"); + expected.put(1, "one"); + expected.put(2, "two"); + expected.put(3, "three"); + expected.put(4, "four"); + expected.put(5, "five"); + expected.put(6, "six"); + expected.put(7, "seven"); + expected.put(8, "eight"); + expected.put(9, "nine"); + expected.put(10, "ten"); + checkCollector("toConcurrentMap", expected, expected.entrySet()::stream, + MoreCollectors.toConcurrentMap()); + } + @Test public void testFlatMapping() { assertThrows(NullPointerException.class, () -> MoreCollectors.flatMapping(null)); From 4891d44e74c62591c73d44bc2cc71d323ce66e49 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Tue, 9 Jun 2020 19:11:41 +0300 Subject: [PATCH 12/29] squash! Define all shortcut signatures --- .../one/util/streamex/MoreCollectors.java | 21 +++---- .../one/util/streamex/MoreCollectorsTest.java | 57 +++---------------- 2 files changed, 18 insertions(+), 60 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 11a93ab9..14dccddc 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -170,53 +170,50 @@ private MoreCollectors() { } - public static Collector, ?, Map> toMap() { + public static Collector, ?, Map> entriesToMap() { return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue); } - public static Collector, ?, ConcurrentMap> toConcurrentMap() { - return Collectors.toConcurrentMap(Map.Entry::getKey, Map.Entry::getValue); - } - - public static Collector, ?, Map> toMap( + public static Collector, ?, Map> entriesToMap( BinaryOperator combiner) { return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, combiner); } - public static Collector, ?, Map> toMap( + public static Collector, ?, Map> entriesToMap( Function valueMapper) { return null; } - public static Collector, ?, Map> toMap( + public static Collector, ?, Map> entriesToMap( Function valueMapper, BinaryOperator combiner) { Objects.requireNonNull(valueMapper); return null; } - public static > Collector, ?, M> toCustomMap( + public static > Collector, ?, M> entriesToCustomMap( Supplier mapSupplier) { return null; } - public static > Collector, ?, M> toCustomMap( + public static > Collector, ?, M> entriesToCustomMap( + Function valueMapper, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); return null; } - public static > Collector, ?, M> toCustomMap( + public static > Collector, ?, M> entriesToCustomMap( BinaryOperator combiner, Supplier mapSupplier) { return null; } - public static > Collector, ?, M> toCustomMap( + public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 869090ed..7b9d3c4a 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -33,8 +33,6 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -594,62 +592,25 @@ public void testToEnumSet() { } @Test - public void testToMap() { + public void testEntriesToMap() { assertThrows(IllegalStateException.class, () -> - EntryStream.generate(() -> "a", () -> 1).limit(10).collect(MoreCollectors.toMap())); + EntryStream.generate(() -> "a", () -> 1).limit(10).collect(MoreCollectors.entriesToMap())); - assertThrows(NullPointerException.class, () -> MoreCollectors.toMap(null, null)); + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(null, null)); - { - Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****") - .collect(MoreCollectors.toMap()); - checkCollector("toMap", expected, expected.entrySet()::stream, MoreCollectors.toMap()); - } + checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToMap()); - final Map expected = new HashMap<>(); - expected.put(1, "one"); - expected.put(2, "two"); - expected.put(3, "three"); - expected.put(4, "four"); - expected.put(5, "five"); + Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****", 5, "*****").toMap(); - checkCollector("toMap", expected, expected.entrySet()::stream, MoreCollectors.toMap()); + checkCollector("entriesToMap", expected, expected.entrySet()::stream, MoreCollectors.entriesToMap()); streamEx(expected.entrySet()::stream, supplier -> { - Map result = supplier.get().collect(MoreCollectors.toMap()); - assertEquals("one", result.get(1)); - assertEquals("two", result.get(2)); - assertEquals("three", result.get(3)); - assertEquals("four", result.get(4)); - assertEquals("five", result.get(5)); - }); - - checkCollectorEmpty("Empty", Collections.emptyMap(), MoreCollectors.toMap()); - - /*streamEx(EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****")::stream, supplier -> { - Map result = supplier.get().collect(MoreCollectors.toMap()); + Map result = supplier.get().collect(MoreCollectors.entriesToMap()); assertEquals("*", result.get(1)); assertEquals("**", result.get(2)); assertEquals("***", result.get(3)); assertEquals("****", result.get(4)); - });*/ - } - - @Test - public void toConcurrentMap() { - final ConcurrentMap expected = new ConcurrentHashMap<>(); - expected.put(0, "zero"); - expected.put(1, "one"); - expected.put(2, "two"); - expected.put(3, "three"); - expected.put(4, "four"); - expected.put(5, "five"); - expected.put(6, "six"); - expected.put(7, "seven"); - expected.put(8, "eight"); - expected.put(9, "nine"); - expected.put(10, "ten"); - checkCollector("toConcurrentMap", expected, expected.entrySet()::stream, - MoreCollectors.toConcurrentMap()); + assertEquals("*****", result.get(5)); + }); } @Test From c38e7bc267cdc046a6a97b3d6c7d438b1f257007 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Wed, 10 Jun 2020 00:46:59 +0300 Subject: [PATCH 13/29] Test entitiesToMap with consumer --- .../one/util/streamex/MoreCollectorsTest.java | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 7b9d3c4a..114dca55 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -600,16 +600,49 @@ public void testEntriesToMap() { checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToMap()); - Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****", 5, "*****").toMap(); + { + Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****", 5, "*****").toMap(); + Supplier>> stream = expected.entrySet()::stream; + checkCollector("entriesToMap", expected, stream, MoreCollectors.entriesToMap()); + + streamEx(stream, supplier -> { + Map result = supplier.get().collect(MoreCollectors.entriesToMap()); + assertEquals("*", result.get(1)); + assertEquals("**", result.get(2)); + assertEquals("***", result.get(3)); + assertEquals("****", result.get(4)); + assertEquals("*****", result.get(5)); + }); + } + } - checkCollector("entriesToMap", expected, expected.entrySet()::stream, MoreCollectors.entriesToMap()); - streamEx(expected.entrySet()::stream, supplier -> { - Map result = supplier.get().collect(MoreCollectors.entriesToMap()); - assertEquals("*", result.get(1)); - assertEquals("**", result.get(2)); + @Test + public void testEntriesToMapWithCombiner() { + streamEx(() -> Stream.of( + EntryStream.of(1, "*").toMap(), + EntryStream.of(1, "*", 2, "*").toMap(), + EntryStream.of(1, "*", 2, "*", 3, "*").toMap(), + EntryStream.of(1, "*", 2, "*", 3, "*", 4, "*").toMap(), + EntryStream.of(1, "*", 2, "*", 3, "*", 4, "*", 5, "*").toMap()) + .flatMap(map -> map.entrySet().stream()), supplier -> { + Map result = supplier.get().collect(MoreCollectors.entriesToMap(String::concat)); + assertEquals("*****", result.get(1)); + assertEquals("****", result.get(2)); assertEquals("***", result.get(3)); - assertEquals("****", result.get(4)); - assertEquals("*****", result.get(5)); + assertEquals("**", result.get(4)); + assertEquals("*", result.get(5)); + }); + + streamEx(() -> Stream.of( + EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four").toMap(), + EntryStream.of(1, "ein", 2, "zwei", 3, "drei").toMap(), + EntryStream.of(1, "une", 2, "deux").toMap()) + .flatMap(map -> map.entrySet().stream()), supplier -> { + Map result = supplier.get().collect(MoreCollectors.entriesToMap((left, right) -> left + "," + right)); + assertEquals("one,ein,une", result.get(1)); + assertEquals("two,zwei,deux", result.get(2)); + assertEquals("three,drei", result.get(3)); + assertEquals("four", result.get(4)); }); } From 2ce6e7d1e3c218ec6d5ae77a950b2eb768a493ce Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Wed, 10 Jun 2020 19:28:29 +0300 Subject: [PATCH 14/29] Implement all entriesToMap and entriesToCustomMap methods --- .../one/util/streamex/MoreCollectors.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 14dccddc..77b5ecc2 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -34,7 +34,6 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.Set; -import java.util.concurrent.ConcurrentMap; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BiPredicate; @@ -171,55 +170,53 @@ private MoreCollectors() { public static Collector, ?, Map> entriesToMap() { - return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue); + return Collectors.toMap(Entry::getKey, Entry::getValue); } public static Collector, ?, Map> entriesToMap( BinaryOperator combiner) { - - return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, combiner); + return Collectors.toMap(Entry::getKey, Entry::getValue, combiner); } public static Collector, ?, Map> entriesToMap( Function valueMapper) { - - return null; + return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue())); } public static Collector, ?, Map> entriesToMap( Function valueMapper, BinaryOperator combiner) { - Objects.requireNonNull(valueMapper); - return null; + return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), combiner); } public static > Collector, ?, M> entriesToCustomMap( Supplier mapSupplier) { - - return null; + return Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), mapSupplier); } public static > Collector, ?, M> entriesToCustomMap( - Function valueMapper, Supplier mapSupplier) { - Objects.requireNonNull(valueMapper); - return null; + return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), throwingMerger(), mapSupplier); } public static > Collector, ?, M> entriesToCustomMap( BinaryOperator combiner, Supplier mapSupplier) { - - return null; + return Collectors.toMap(Entry::getKey, Entry::getValue, combiner, mapSupplier); } public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); - return null; + return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), combiner, mapSupplier); } + private static BinaryOperator throwingMerger() { + return (firstKey, secondKey) -> { + throw new IllegalStateException("Duplicate entry keys are not allowed (attempt to merge key '" + firstKey + "'). "); + }; + } /** * Returns a {@code Collector} which counts a number of distinct values the From 427074d33078f5bef2a56763ee1446814c6929f4 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Wed, 10 Jun 2020 19:35:29 +0300 Subject: [PATCH 15/29] Implement all entriesToMap and entriesToCustomMap methods --- .../java/one/util/streamex/MoreCollectorsTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 114dca55..aa5c3a26 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -646,6 +646,18 @@ public void testEntriesToMapWithCombiner() { }); } + @Test + public void testEntriesToMapWithValueMapper() { + streamEx(() -> EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), + supplier -> { + Map result = supplier.get().collect(MoreCollectors.entriesToMap((value) -> "See #" + value)); + assertEquals("See #one", result.get(1)); + assertEquals("See #two", result.get(2)); + assertEquals("See #three", result.get(3)); + assertEquals("See #four", result.get(4)); + }); + } + @Test public void testFlatMapping() { assertThrows(NullPointerException.class, () -> MoreCollectors.flatMapping(null)); From 4275348a68e644183b6d6d43262306b9774d0ab5 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Thu, 11 Jun 2020 10:37:59 +0300 Subject: [PATCH 16/29] Improve formatting for new signatures --- src/main/java/one/util/streamex/MoreCollectors.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 77b5ecc2..71217ec6 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -168,18 +168,15 @@ private MoreCollectors() { }, Function.identity(), set -> set.size() == size, UNORDERED_ID_CHARACTERISTICS); } - public static Collector, ?, Map> entriesToMap() { return Collectors.toMap(Entry::getKey, Entry::getValue); } - public static Collector, ?, Map> entriesToMap( - BinaryOperator combiner) { + public static Collector, ?, Map> entriesToMap(BinaryOperator combiner) { return Collectors.toMap(Entry::getKey, Entry::getValue, combiner); } - public static Collector, ?, Map> entriesToMap( - Function valueMapper) { + public static Collector, ?, Map> entriesToMap(Function valueMapper) { return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue())); } @@ -207,7 +204,6 @@ private MoreCollectors() { public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { - Objects.requireNonNull(valueMapper); return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), combiner, mapSupplier); } From 2e0b737b43fd394085e3a053a7e0102b4751ab6f Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Thu, 11 Jun 2020 10:38:04 +0300 Subject: [PATCH 17/29] Test entriesToMap with value mapper and combiner --- .../one/util/streamex/MoreCollectorsTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index aa5c3a26..02c85f2f 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -33,6 +33,7 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -658,6 +659,22 @@ public void testEntriesToMapWithValueMapper() { }); } + @Test + public void testEntriesToMapWithValueMapperAndCombiner() { + streamEx(() -> Stream.of( + EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four").toMap(), + EntryStream.of(1, "ein", 2, "zwei", 3, "drei").toMap(), + EntryStream.of(1, "une", 2, "deux").toMap()) + .flatMap(map -> map.entrySet().stream()), supplier -> { + Map result = supplier.get().collect( + MoreCollectors.entriesToMap((value) -> "['" + value + "']", (left, right) -> left + ", " + right)); + assertEquals("['one'], ['ein'], ['une']", result.get(1)); + assertEquals("['two'], ['zwei'], ['deux']", result.get(2)); + assertEquals("['three'], ['drei']", result.get(3)); + assertEquals("['four']", result.get(4)); + }); + } + @Test public void testFlatMapping() { assertThrows(NullPointerException.class, () -> MoreCollectors.flatMapping(null)); From 6aae10d134394260d1cc45b34b3a2732a0ce2df9 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Thu, 11 Jun 2020 11:03:48 +0300 Subject: [PATCH 18/29] Extend test entriesToMap with value mapper --- .../java/one/util/streamex/MoreCollectorsTest.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 02c85f2f..957a699b 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -33,7 +33,6 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -657,6 +656,18 @@ public void testEntriesToMapWithValueMapper() { assertEquals("See #three", result.get(3)); assertEquals("See #four", result.get(4)); }); + + streamEx(() -> StreamEx.of("Bran Stark", "Arya Stark", "Jon Snow", "Tyrion (The Imp) Lannister", "Theon Greyjoy", + "Ser Jaime (The Kingslayer) Lannister", "Daenerys Stormborn Targaryen", "Khal Drogo", "Ser Jorah Mormont") + .mapToEntry(name -> name.contains("Khal") || name.contains("Ser")), supplier -> { + Map result = supplier.get().collect( + MoreCollectors.entriesToMap((value) -> { + return value ? "This character has celebrity title" : "Standard character"; + })); + assertEquals("This character has celebrity title", result.get("Khal Drogo")); + assertEquals("Standard character", result.get("Jon Snow")); + assertEquals("This character has celebrity title", result.get("Ser Jorah Mormont")); + }); } @Test From 44e680bac3dae73ded5c71093e61c8c4cf0209a5 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Sat, 13 Jun 2020 01:42:16 +0300 Subject: [PATCH 19/29] Add javadoc to all entriesToMap methods. --- .../one/util/streamex/MoreCollectors.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 71217ec6..53344e5a 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -168,18 +168,89 @@ private MoreCollectors() { }, Function.identity(), set -> set.size() == size, UNORDERED_ID_CHARACTERISTICS); } + /** + * Returns a {@code Collector} that accumulates elements into a {@code Map} + * whose keys and values are taken from {@code Map.Entry}. + * + * @param the {@link Comparable} type of then map keys + * @param the type of the map values + * + * @return {@code Collector} which collects elements into a {@code Map} + * whose keys and values are taken from {@code Map.Entry} + * @throws IllegalStateException if this stream contains duplicate keys + * (according to {@link Object#equals(Object)}) + * @see Collectors#toMap(Function, Function) + */ public static Collector, ?, Map> entriesToMap() { return Collectors.toMap(Entry::getKey, Entry::getValue); } + /** + * Returns a {@code Collector} that accumulates elements into a {@code Map} + * whose keys and values are taken from {@code Map.Entry} and combining them + * using the provided {@code combiner} function to the input elements. + * + *

If the mapped keys contains duplicates (according to {@link Object#equals(Object)}), + * the value mapping function is applied to each equal element, and the + * results are merged using the provided {@code combiner} function. + * + * @param the {@link Comparable} type of then map keys + * @param the type of the map values + * @param combiner a merge function, used to resolve collisions between + * values associated with the same key, as supplied + * to {@link Map#merge(Object, Object, BiFunction)} + * @return {@code Collector} which collects elements into a {@code Map} + * whose keys and values are taken from {@code Map.Entry} and combining them + * using the {@code combiner} function + * @throws IllegalStateException if this stream contains duplicate keys + * (according to {@link Object#equals(Object)}) + * @see Collectors#toMap(Function, Function, BinaryOperator) + */ public static Collector, ?, Map> entriesToMap(BinaryOperator combiner) { return Collectors.toMap(Entry::getKey, Entry::getValue, combiner); } + /** + * Returns a {@code Collector} that accumulates elements into a {@code Map} + * whose keys are taken from {@code Map.Entry} and values are the result + * of applying the provided {@code valueMapper} function. + * + * @param the {@link Comparable} type of then map keys + * @param the type of the map values + * @param the output type of the value mapping function + * @param valueMapper a mapping function to produce values from {@code Map.Entry} values + * @return {@code Collector} which collects elements into a {@code Map} + * whose keys are taken from {@code Map.Entry} and values are the result of applying + * the provided {@code valueMapper} function to {@code Map.Entry} values. + * @throws IllegalStateException if this stream contains duplicate keys + * (according to {@link Object#equals(Object)}) + * @see Collectors#toMap(Function, Function) + */ public static Collector, ?, Map> entriesToMap(Function valueMapper) { return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue())); } + /** + * Returns a {@code Collector} that accumulates elements into a {@code Map} + * whose keys are taken from {@code Map.Entry} and values are the result + * of applying the provided {@code valueMapper} function and combining them + * using the provided {@code combiner} function to {@code Map.Entry} values of input elements. + * + * @param the {@link Comparable} type of then map keys + * @param the type of the map values + * @param the output type of the value mapping function + * @param valueMapper a mapping function to produce values + * @param combiner a merge function, used to resolve collisions between + * values associated with the same key, as supplied + * to {@link Map#merge(Object, Object, BiFunction)} + * @return {@code Collector} which collects elements into a {@code Map} + * whose keys are taken from {@code Map.Entry} and values are the result + * of applying the provided {@code valueMapper} function and combining + * them using the provided {@code combiner} function to the input elements. + * @throws IllegalStateException if this stream contains duplicate keys + * (according to {@link Object#equals(Object)}) + * @see Collectors#toMap(Function, Function, BinaryOperator) + */ public static Collector, ?, Map> entriesToMap( Function valueMapper, BinaryOperator combiner) { Objects.requireNonNull(valueMapper); From 4fc2bf5db74d6e434300a64b830f1a42deb52880 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Sat, 13 Jun 2020 01:43:44 +0300 Subject: [PATCH 20/29] Update CHANGES.md --- wiki/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/wiki/CHANGES.md b/wiki/CHANGES.md index 573a4962..b7196061 100644 --- a/wiki/CHANGES.md +++ b/wiki/CHANGES.md @@ -4,6 +4,7 @@ Check also [MIGRATION.md](MIGRATION.md) for possible compatibility problems. ### 0.7.3 * [#028]: Added: `StreamEx.toCollectionAndThen` +* [#043]: Added: Add `MoreCollectors.entriesToMap` and `MoreCollectors.entriesToCustomMap` methods accepting Entry. * [#219]: Changed: MoreCollectors now reject eagerly null parameters where possible; `MoreCollectors.last` throws NPE if last stream element is null. * [#221]: Fixed: `rangeClosed(x, x, step)` returned empty stream instead of stream of `x` if step absolute value is bigger than one. From 995852976189f21d2c3711d85a7dcdb71882a066 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Sat, 13 Jun 2020 02:26:10 +0300 Subject: [PATCH 21/29] Javadoc for entriesToCustomMap methods --- .../one/util/streamex/MoreCollectors.java | 106 ++++++++++++++++-- 1 file changed, 97 insertions(+), 9 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 53344e5a..f589da62 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -179,6 +179,7 @@ private MoreCollectors() { * whose keys and values are taken from {@code Map.Entry} * @throws IllegalStateException if this stream contains duplicate keys * (according to {@link Object#equals(Object)}) + * * @see Collectors#toMap(Function, Function) */ public static Collector, ?, Map> entriesToMap() { @@ -202,8 +203,7 @@ private MoreCollectors() { * @return {@code Collector} which collects elements into a {@code Map} * whose keys and values are taken from {@code Map.Entry} and combining them * using the {@code combiner} function - * @throws IllegalStateException if this stream contains duplicate keys - * (according to {@link Object#equals(Object)}) + * * @see Collectors#toMap(Function, Function, BinaryOperator) */ public static Collector, ?, Map> entriesToMap(BinaryOperator combiner) { @@ -224,6 +224,7 @@ private MoreCollectors() { * the provided {@code valueMapper} function to {@code Map.Entry} values. * @throws IllegalStateException if this stream contains duplicate keys * (according to {@link Object#equals(Object)}) + * * @see Collectors#toMap(Function, Function) */ public static Collector, ?, Map> entriesToMap(Function valueMapper) { @@ -231,10 +232,10 @@ private MoreCollectors() { } /** - * Returns a {@code Collector} that accumulates elements into a {@code Map} + * Returns a {@code Collector} that accumulates input elements into a {@code Map} * whose keys are taken from {@code Map.Entry} and values are the result - * of applying the provided {@code valueMapper} function and combining them - * using the provided {@code combiner} function to {@code Map.Entry} values of input elements. + * of applying the provided {@code valueMapper} function to {@code Map.Entry} values + * and combining them using the provided {@code combiner} function. * * @param the {@link Comparable} type of then map keys * @param the type of the map values @@ -246,9 +247,8 @@ private MoreCollectors() { * @return {@code Collector} which collects elements into a {@code Map} * whose keys are taken from {@code Map.Entry} and values are the result * of applying the provided {@code valueMapper} function and combining - * them using the provided {@code combiner} function to the input elements. - * @throws IllegalStateException if this stream contains duplicate keys - * (according to {@link Object#equals(Object)}) + * them using the provided {@code combiner} function. + * * @see Collectors#toMap(Function, Function, BinaryOperator) */ public static Collector, ?, Map> entriesToMap( @@ -257,22 +257,108 @@ private MoreCollectors() { return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), combiner); } + /** + * Returns a {@code Collector} that accumulates elements into + * a result {@code Map} defined by {@code mapSupplier} function + * whose keys and values are taken from {@code Map.Entry}. + * + * @param the {@link Comparable} type of then map keys + * @param the type of the map values + * @param the type of the resulting {@code Map} + * @return {@code Collector} which collects elements into a {@code Map} + * defined by {@code mapSupplier} function + * whose keys and values are taken from {@code Map.Entry} + * @throws IllegalStateException if this stream contains duplicate keys + * (according to {@link Object#equals(Object)}) + * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) + */ public static > Collector, ?, M> entriesToCustomMap( Supplier mapSupplier) { return Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), mapSupplier); } + /** + * Returns a {@code Collector} that accumulates elements into + * a result {@code Map} defined by {@code mapSupplier} function + * whose keys are taken from {@code Map.Entry} and values are the result + * of applying the provided {@code valueMapper} function. + * + * @param the {@link Comparable} type of then map keys + * @param the type of the map values + * @param the output type of the value mapping function + * @param the type of the resulting {@code Map} + * @param valueMapper a mapping function to produce values from {@code Map.Entry} values + * @return {@code Collector} which collects elements into a {@code Map} + * defined by {@code mapSupplier} function whose keys are taken + * from {@code Map.Entry} and values are the result of applying + * the provided {@code valueMapper} function to {@code Map.Entry} values. + * @throws IllegalStateException if this stream contains duplicate keys + * (according to {@link Object#equals(Object)}) + * + * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) + */ public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), throwingMerger(), mapSupplier); } + /** + * Returns a {@code Collector} that accumulates elements into + * a result {@code Map} defined by {@code mapSupplier} function + * whose keys and values are taken from {@code Map.Entry} and combining them + * using the provided {@code combiner} function to the input elements. + * + *

If the mapped keys contains duplicates (according to {@link Object#equals(Object)}), + * the value mapping function is applied to each equal element, and the + * results are merged using the provided {@code combiner} function. + * + * @param the {@link Comparable} type of then map keys + * @param the type of the map values + * @param the type of the resulting {@code Map} + * @param combiner a merge function, used to resolve collisions between + * values associated with the same key, as supplied + * to {@link Map#merge(Object, Object, BiFunction)} + * @param mapSupplier a function which returns a new, empty {@code Map} into + * which the results will be inserted + * @return {@code Collector} which collects elements into a {@code Map} + * whose keys and values are taken from {@code Map.Entry} and combining them + * using the {@code combiner} function + * + * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) + */ public static > Collector, ?, M> entriesToCustomMap( BinaryOperator combiner, Supplier mapSupplier) { return Collectors.toMap(Entry::getKey, Entry::getValue, combiner, mapSupplier); } + /** + * Returns a {@code Collector} that accumulates elements into + * a result {@code Map} defined by {@code mapSupplier} function + * whose keys are taken from {@code Map.Entry} and values are the result + * of applying the provided {@code valueMapper} function to {@code Map.Entry} values + * and combining them using the provided {@code combiner} function. + * + *

If the mapped keys contains duplicates (according to {@link Object#equals(Object)}), + * the value mapping function is applied to each equal element, and the + * results are merged using the provided {@code combiner} function. + * + * @param the {@link Comparable} type of then map keys + * @param the type of the map values + * @param the output type of the value mapping function + * @param the type of the resulting {@code Map} + * @param valueMapper a mapping function to produce values + * @param combiner a merge function, used to resolve collisions between + * values associated with the same key, as supplied + * to {@link Map#merge(Object, Object, BiFunction)} + * @param mapSupplier a function which returns a new, empty {@code Map} into + * which the results will be inserted + * @return {@code Collector} which collects elements into a {@code Map} + * whose keys and values are taken from {@code Map.Entry} and combining them + * using the {@code combiner} function + * + * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) + */ public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); @@ -400,7 +486,9 @@ private static BinaryOperator throwingMerger() { Supplier> supplier = () -> new PairBox<>(c1Supplier.get(), c2Supplier.get()); BiConsumer, T> accumulator = (acc, v) -> { - c1Accumulator.accept(acc.a, v); + + + c2Accumulator.accept(acc.b, v); }; BinaryOperator> combiner = (acc1, acc2) -> { From 3fca619e0a615433d48c660065dc3d2e96237afb Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Sat, 13 Jun 2020 17:00:59 +0300 Subject: [PATCH 22/29] Add tests for different entriesToCustomMap- collectors --- .../one/util/streamex/MoreCollectorsTest.java | 130 +++++++++++++++++- 1 file changed, 125 insertions(+), 5 deletions(-) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 957a699b..43deaf38 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -25,10 +25,12 @@ import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; +import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.NavigableMap; import java.util.Optional; import java.util.OptionalInt; import java.util.OptionalLong; @@ -596,8 +598,6 @@ public void testEntriesToMap() { assertThrows(IllegalStateException.class, () -> EntryStream.generate(() -> "a", () -> 1).limit(10).collect(MoreCollectors.entriesToMap())); - assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(null, null)); - checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToMap()); { @@ -661,9 +661,7 @@ public void testEntriesToMapWithValueMapper() { "Ser Jaime (The Kingslayer) Lannister", "Daenerys Stormborn Targaryen", "Khal Drogo", "Ser Jorah Mormont") .mapToEntry(name -> name.contains("Khal") || name.contains("Ser")), supplier -> { Map result = supplier.get().collect( - MoreCollectors.entriesToMap((value) -> { - return value ? "This character has celebrity title" : "Standard character"; - })); + MoreCollectors.entriesToMap((value) -> value ? "This character has celebrity title" : "Standard character")); assertEquals("This character has celebrity title", result.get("Khal Drogo")); assertEquals("Standard character", result.get("Jon Snow")); assertEquals("This character has celebrity title", result.get("Ser Jorah Mormont")); @@ -672,6 +670,8 @@ public void testEntriesToMapWithValueMapper() { @Test public void testEntriesToMapWithValueMapperAndCombiner() { + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(null, null)); + streamEx(() -> Stream.of( EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four").toMap(), EntryStream.of(1, "ein", 2, "zwei", 3, "drei").toMap(), @@ -686,6 +686,126 @@ public void testEntriesToMapWithValueMapperAndCombiner() { }); } + @Test + public void testEntriesToCustomMap() { + assertThrows(IllegalStateException.class, () -> + EntryStream.generate(() -> "a", () -> 1).limit(10).collect(MoreCollectors.entriesToCustomMap(LinkedHashMap::new))); + + checkCollectorEmpty("entriesToMap", Collections.emptyMap(), + MoreCollectors.entriesToCustomMap(HashMap::new)); + checkCollectorEmpty("entriesToMap", Collections.emptyMap(), + MoreCollectors.entriesToCustomMap(IdentityHashMap::new)); + checkCollectorEmpty("entriesToMap", Collections.emptyNavigableMap(), + MoreCollectors.entriesToCustomMap(TreeMap::new)); + checkCollectorEmpty("entriesToMap", Collections.emptySortedMap(), + MoreCollectors.entriesToCustomMap(TreeMap::new)); + checkCollectorEmpty("entriesToMap", Collections.emptySortedMap(), + MoreCollectors.entriesToCustomMap(LinkedHashMap::new)); + + { + Map expected = EntryStream.of(5, "*****", 1, "*", 4, "****", 2, "**", 3, "***").toMap(); + Supplier>> stream = expected.entrySet()::stream; + checkCollector("entriesToMap", expected, stream, MoreCollectors.entriesToCustomMap(TreeMap::new)); + + streamEx(stream, supplier -> { + NavigableMap result = supplier.get().collect(MoreCollectors.entriesToCustomMap(TreeMap::new)); + assertEquals("*", result.get(1)); + assertEquals("**", result.get(2)); + assertEquals("***", result.get(3)); + assertEquals("****", result.get(4)); + assertEquals("*****", result.get(5)); + + assertEquals(1, (int) result.firstKey()); + assertEquals("*", result.firstEntry().getValue()); + assertEquals(5, (int) result.lastKey()); + assertEquals("*****", result.lastEntry().getValue()); + }); + } + + { + LinkedHashMap expected = EntryStream.of(5, "*****", 1, "*", 4, "****", 2, "**", 3, "***") + .collect(MoreCollectors.entriesToCustomMap(LinkedHashMap::new)); + assertEquals("5=*****", expected.entrySet().iterator().next().toString()); + } + } + + @Test + public void testEntriesToCustomMapWithValueMapper() { + assertThrows(IllegalStateException.class, () -> + EntryStream.generate(() -> "a", () -> 1).limit(10).collect( + MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", LinkedHashMap::new))); + + streamEx(() -> EntryStream.of(5, "*****", 1, "*", 4, "****", 2, "**", 3, "***"), supplier -> { + NavigableMap result = supplier.get().collect( + MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", TreeMap::new)); + assertEquals("1=['*']", result.firstEntry().toString()); + assertEquals("5=['*****']", result.lastEntry().toString()); + }); + + streamEx(() -> EntryStream.of(5, "*****", 1, "*", 4, "****", 2, "**", 3, "***"), supplier -> { + Map result = supplier.get().collect( + MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", LinkedHashMap::new)); + assertEquals("5=['*****']", result.entrySet().iterator().next().toString()); + }); + } + + @Test + public void testEntriesToCustomMapWithCombiner() { + streamEx(() -> Stream.of( + EntryStream.of(100, "hundred", 2, "two", 3, "three", 4, "four").toMap(), + EntryStream.of(100, "hundert", 2, "zwei", 3, "drei").toMap(), + EntryStream.of(100, "cent", 2, "deux").toMap()) + .flatMap(map -> map.entrySet().stream()), supplier -> { + NavigableMap result = supplier.get().collect( + MoreCollectors.entriesToCustomMap((left, right) -> left + " -> " + right, TreeMap::new)); + assertEquals("hundred -> hundert -> cent", result.get(100)); + assertEquals("two -> zwei -> deux", result.get(2)); + assertEquals("three -> drei", result.get(3)); + assertEquals("four", result.get(4)); + + assertEquals(2, (int) result.firstKey()); + assertEquals("two -> zwei -> deux", result.firstEntry().getValue()); + assertEquals(100, (int) result.lastKey()); + assertEquals("hundred -> hundert -> cent", result.lastEntry().getValue()); + }); + + streamEx(() -> Stream.of( + EntryStream.of(10, "*").toMap(), + EntryStream.of(10, "*", 2, "*").toMap(), + EntryStream.of(10, "*", 2, "*", 100, "*").toMap(), + EntryStream.of(10, "*", 2, "*", 100, "*", 4, "*").toMap(), + EntryStream.of(10, "*", 2, "*", 100, "*", 4, "*", 5, "*").toMap()) + .flatMap(map -> map.entrySet().stream()), supplier -> { + + NavigableMap result = supplier.get().collect( + MoreCollectors.entriesToCustomMap((left, right) -> left + " -> " + right, TreeMap::new)); + assertEquals("2=* -> * -> * -> *", result.entrySet().iterator().next().toString()); + }); + } + + @Test + public void testEntriesToCustomMapWithValueMapperAndCombiner() { + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, null, null)); + + streamEx(() -> Stream.of( + EntryStream.of(100, "hundred", 2, "two", 3, "three", 4, "four").toMap(), + EntryStream.of(100, "hundert", 2, "zwei", 3, "drei").toMap(), + EntryStream.of(100, "cent", 2, "deux").toMap()) + .flatMap(map -> map.entrySet().stream()), supplier -> { + NavigableMap result = supplier.get().collect( + MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", (left, right) -> left + ", " + right, TreeMap::new)); + assertEquals("['hundred'], ['hundert'], ['cent']", result.get(100)); + assertEquals("['two'], ['zwei'], ['deux']", result.get(2)); + assertEquals("['three'], ['drei']", result.get(3)); + assertEquals("['four']", result.get(4)); + + assertEquals(2, (int) result.firstKey()); + assertEquals("['two'], ['zwei'], ['deux']", result.firstEntry().getValue()); + assertEquals(100, (int) result.lastKey()); + assertEquals("['hundred'], ['hundert'], ['cent']", result.lastEntry().getValue()); + }); + } + @Test public void testFlatMapping() { assertThrows(NullPointerException.class, () -> MoreCollectors.flatMapping(null)); From 8771571f965fe428df9f4f746b40be309270884b Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Sat, 13 Jun 2020 17:00:59 +0300 Subject: [PATCH 23/29] Add tests for different entriesToCustomMap- collectors --- src/main/java/one/util/streamex/MoreCollectors.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index f589da62..9237c2aa 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -486,9 +486,7 @@ private static BinaryOperator throwingMerger() { Supplier> supplier = () -> new PairBox<>(c1Supplier.get(), c2Supplier.get()); BiConsumer, T> accumulator = (acc, v) -> { - - - + c1Accumulator.accept(acc.a, v); c2Accumulator.accept(acc.b, v); }; BinaryOperator> combiner = (acc1, acc2) -> { From 996aa5c69ee3ddb2aff80a74720bfa85a77cb642 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Sat, 13 Jun 2020 17:18:46 +0300 Subject: [PATCH 24/29] Improve javadoc of new test methods --- .../one/util/streamex/MoreCollectorsTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 43deaf38..7cdc1bee 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -37,6 +37,7 @@ import java.util.TreeMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; @@ -593,6 +594,9 @@ public void testToEnumSet() { checkCollectorEmpty("Empty", EnumSet.noneOf(TimeUnit.class), MoreCollectors.toEnumSet(TimeUnit.class)); } + /** + * See {@link MoreCollectors#entriesToMap()}. + */ @Test public void testEntriesToMap() { assertThrows(IllegalStateException.class, () -> @@ -616,6 +620,9 @@ public void testEntriesToMap() { } } + /** + * See {@link MoreCollectors#entriesToMap(BinaryOperator)}. + */ @Test public void testEntriesToMapWithCombiner() { streamEx(() -> Stream.of( @@ -646,6 +653,9 @@ public void testEntriesToMapWithCombiner() { }); } + /** + * See {@link MoreCollectors#entriesToMap(Function)}. + */ @Test public void testEntriesToMapWithValueMapper() { streamEx(() -> EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), @@ -668,6 +678,9 @@ public void testEntriesToMapWithValueMapper() { }); } + /** + * See {@link MoreCollectors#entriesToMap(Function, BinaryOperator)}. + */ @Test public void testEntriesToMapWithValueMapperAndCombiner() { assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(null, null)); @@ -686,6 +699,9 @@ public void testEntriesToMapWithValueMapperAndCombiner() { }); } + /** + * See {@link MoreCollectors#entriesToCustomMap(Supplier)}. + */ @Test public void testEntriesToCustomMap() { assertThrows(IllegalStateException.class, () -> @@ -729,6 +745,9 @@ public void testEntriesToCustomMap() { } } + /** + * See {@link MoreCollectors#entriesToCustomMap(Function, Supplier)}. + */ @Test public void testEntriesToCustomMapWithValueMapper() { assertThrows(IllegalStateException.class, () -> @@ -749,6 +768,9 @@ public void testEntriesToCustomMapWithValueMapper() { }); } + /** + * See {@link MoreCollectors#entriesToCustomMap(BinaryOperator, Supplier)}. + */ @Test public void testEntriesToCustomMapWithCombiner() { streamEx(() -> Stream.of( @@ -783,6 +805,9 @@ public void testEntriesToCustomMapWithCombiner() { }); } + /** + * See {@link MoreCollectors#entriesToCustomMap(Function, BinaryOperator, Supplier)}. + */ @Test public void testEntriesToCustomMapWithValueMapperAndCombiner() { assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, null, null)); From d4a1bf43c2b3952d467c234a2680ad9d4de7fb3c Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Sun, 14 Jun 2020 15:24:06 +0300 Subject: [PATCH 25/29] Add new collectors to CHEATSHEET --- wiki/CHEATSHEET.md | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/wiki/CHEATSHEET.md b/wiki/CHEATSHEET.md index cc031895..40730e1e 100644 --- a/wiki/CHEATSHEET.md +++ b/wiki/CHEATSHEET.md @@ -5,25 +5,25 @@ * [Glossary](#glossary) * [Stream sources](#stream-sources) * [New intermediate operations](#new-intermediate-operations) - * [filtering](#filtering) - * [mapping](#mapping) - * [flat-mapping](#flat-mapping) - * [distinct](#distinct) - * [sorting](#sorting) - * [partial reduction](#partial-reduction) - * [concatenate](#concatenate) - * [peek](#peek) - * [misc](#misc-intermediate-operations) + * [filtering](#filtering) + * [mapping](#mapping) + * [flat-mapping](#flat-mapping) + * [distinct](#distinct) + * [sorting](#sorting) + * [partial reduction](#partial-reduction) + * [concatenate](#concatenate) + * [peek](#peek) + * [misc](#misc-intermediate-operations) * [New terminal operations](#new-terminal-operations) - * [Collector shortcuts](#collector-shortcuts) - * [Search](#search) - * [Folding](#folding) - * [Primitive operations](#primitive-operations) - * [forEach-like operations](#foreach-like-operations) - * [misc](#misc-terminal-operations) + * [Collector shortcuts](#collector-shortcuts) + * [Search](#search) + * [Folding](#folding) + * [Primitive operations](#primitive-operations) + * [forEach-like operations](#foreach-like-operations) + * [misc](#misc-terminal-operations) * [Collectors](#collectors) - * [Basic collectors](#basic-collectors) - * [Adaptor collectors](#adaptor-collectors) + * [Basic collectors](#basic-collectors) + * [Adaptor collectors](#adaptor-collectors) ## Glossary @@ -259,7 +259,8 @@ What I want | How to get it --- | --- Collect to array | `MoreCollectors.toArray()` Collect to boolean array using the `Predicate` applied to each element | `MoreCollectors.toBooleanArray()` -Collect to `EnumSet` | `MoreCollectors.toEnumSet()` +Collect `Map.Entry` entries to `HashMap` | `MoreCollectors.entriesToMap()` +Collect `Map.Entry` entries to cstom `Map` implementation | `MoreCollectors.entriesToCustomMap()` Count number of distinct elements using custom key extractor | `MoreCollectors.distinctCount()` Get the `List` of distinct elements using custom key extractor | `MoreCollectors.distinctBy()` Simply counting, but get the result as `Integer` | `MoreCollectors.countingInt()` @@ -287,4 +288,4 @@ Filter the input before passing to the collector | `MoreCollectors.filtering()` Map the input before passing to the collector | `MoreCollectors.mapping()` Flat-map the input before passing to the collector | `MoreCollectors.flatMapping()` Perform a custom final operation after the collection finishes | `MoreCollectors.collectingAndThen()` -Perform a downstream collection if all elements satisfy the predicate | `MoreCollectors.ifAllMatch()` \ No newline at end of file +Perform a downstream collection if all elements satisfy the predicate | `MoreCollectors.ifAllMatch()` From 8439c4b16ae8ddf71e969bbd93cf498490372f0b Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Mon, 15 Jun 2020 11:07:36 +0300 Subject: [PATCH 26/29] Apply code review points - Add @since tags - Add more @see tags to crosslink overloads - Fix typos --- .../one/util/streamex/MoreCollectors.java | 33 +++++++++++++++++++ wiki/CHEATSHEET.md | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 9237c2aa..2ac945b2 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -180,7 +180,11 @@ private MoreCollectors() { * @throws IllegalStateException if this stream contains duplicate keys * (according to {@link Object#equals(Object)}) * + * @see #entriesToMap(BinaryOperator) + * @see #entriesToMap(Function) + * @see #entriesToMap(Function, BinaryOperator) * @see Collectors#toMap(Function, Function) + * @since 0.7.3 */ public static Collector, ?, Map> entriesToMap() { return Collectors.toMap(Entry::getKey, Entry::getValue); @@ -204,7 +208,11 @@ private MoreCollectors() { * whose keys and values are taken from {@code Map.Entry} and combining them * using the {@code combiner} function * + * @see #entriesToMap() + * @see #entriesToMap(Function) + * @see #entriesToMap(Function, BinaryOperator) * @see Collectors#toMap(Function, Function, BinaryOperator) + * @since 0.7.3 */ public static Collector, ?, Map> entriesToMap(BinaryOperator combiner) { return Collectors.toMap(Entry::getKey, Entry::getValue, combiner); @@ -225,7 +233,11 @@ private MoreCollectors() { * @throws IllegalStateException if this stream contains duplicate keys * (according to {@link Object#equals(Object)}) * + * @see #entriesToMap() + * @see #entriesToMap(BinaryOperator) + * @see #entriesToMap(Function, BinaryOperator) * @see Collectors#toMap(Function, Function) + * @since 0.7.3 */ public static Collector, ?, Map> entriesToMap(Function valueMapper) { return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue())); @@ -249,7 +261,11 @@ private MoreCollectors() { * of applying the provided {@code valueMapper} function and combining * them using the provided {@code combiner} function. * + * @see #entriesToMap() + * @see #entriesToMap(BinaryOperator) + * @see #entriesToMap(Function) * @see Collectors#toMap(Function, Function, BinaryOperator) + * @since 0.7.3 */ public static Collector, ?, Map> entriesToMap( Function valueMapper, BinaryOperator combiner) { @@ -270,7 +286,12 @@ private MoreCollectors() { * whose keys and values are taken from {@code Map.Entry} * @throws IllegalStateException if this stream contains duplicate keys * (according to {@link Object#equals(Object)}) + * + * @see #entriesToCustomMap(Function, Supplier) + * @see #entriesToCustomMap(BinaryOperator, Supplier) + * @see #entriesToCustomMap(Function, BinaryOperator, Supplier) * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) + * @since 0.7.3 */ public static > Collector, ?, M> entriesToCustomMap( Supplier mapSupplier) { @@ -295,7 +316,11 @@ private MoreCollectors() { * @throws IllegalStateException if this stream contains duplicate keys * (according to {@link Object#equals(Object)}) * + * @see #entriesToCustomMap(Supplier) + * @see #entriesToCustomMap(BinaryOperator, Supplier) + * @see #entriesToCustomMap(Function, BinaryOperator, Supplier) * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) + * @since 0.7.3 */ public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, Supplier mapSupplier) { @@ -325,7 +350,11 @@ private MoreCollectors() { * whose keys and values are taken from {@code Map.Entry} and combining them * using the {@code combiner} function * + * @see #entriesToCustomMap(Supplier) + * @see #entriesToCustomMap(Function, Supplier) + * @see #entriesToCustomMap(Function, BinaryOperator, Supplier) * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) + * @since 0.7.3 */ public static > Collector, ?, M> entriesToCustomMap( BinaryOperator combiner, Supplier mapSupplier) { @@ -357,7 +386,11 @@ private MoreCollectors() { * whose keys and values are taken from {@code Map.Entry} and combining them * using the {@code combiner} function * + * @see #entriesToCustomMap(Supplier) + * @see #entriesToCustomMap(Function, Supplier) + * @see #entriesToCustomMap(BinaryOperator, Supplier) * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) + * @since 0.7.3 */ public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { diff --git a/wiki/CHEATSHEET.md b/wiki/CHEATSHEET.md index 40730e1e..6a1243ef 100644 --- a/wiki/CHEATSHEET.md +++ b/wiki/CHEATSHEET.md @@ -260,7 +260,7 @@ What I want | How to get it Collect to array | `MoreCollectors.toArray()` Collect to boolean array using the `Predicate` applied to each element | `MoreCollectors.toBooleanArray()` Collect `Map.Entry` entries to `HashMap` | `MoreCollectors.entriesToMap()` -Collect `Map.Entry` entries to cstom `Map` implementation | `MoreCollectors.entriesToCustomMap()` +Collect `Map.Entry` entries to custom `Map` implementation | `MoreCollectors.entriesToCustomMap()` Count number of distinct elements using custom key extractor | `MoreCollectors.distinctCount()` Get the `List` of distinct elements using custom key extractor | `MoreCollectors.distinctBy()` Simply counting, but get the result as `Integer` | `MoreCollectors.countingInt()` From ab984a022a48531872ce91c2e7448000b7b02d84 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Mon, 15 Jun 2020 12:13:42 +0300 Subject: [PATCH 27/29] Apply code review points - Optimize merging EntryStream(s) - Document NPE in case of mapSupplier is null(and ensure it's actually thrown) --- .../one/util/streamex/MoreCollectors.java | 13 ++-- .../one/util/streamex/MoreCollectorsTest.java | 65 +++++++++++-------- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 2ac945b2..3f5fe0ef 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -178,7 +178,7 @@ private MoreCollectors() { * @return {@code Collector} which collects elements into a {@code Map} * whose keys and values are taken from {@code Map.Entry} * @throws IllegalStateException if this stream contains duplicate keys - * (according to {@link Object#equals(Object)}) + * (according to {@link Object#equals(Object)}). * * @see #entriesToMap(BinaryOperator) * @see #entriesToMap(Function) @@ -231,7 +231,8 @@ private MoreCollectors() { * whose keys are taken from {@code Map.Entry} and values are the result of applying * the provided {@code valueMapper} function to {@code Map.Entry} values. * @throws IllegalStateException if this stream contains duplicate keys - * (according to {@link Object#equals(Object)}) + * (according to {@link Object#equals(Object)}). + * @throws NullPointerException if mapper is null. * * @see #entriesToMap() * @see #entriesToMap(BinaryOperator) @@ -240,6 +241,7 @@ private MoreCollectors() { * @since 0.7.3 */ public static Collector, ?, Map> entriesToMap(Function valueMapper) { + Objects.requireNonNull(valueMapper); return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue())); } @@ -260,6 +262,7 @@ private MoreCollectors() { * whose keys are taken from {@code Map.Entry} and values are the result * of applying the provided {@code valueMapper} function and combining * them using the provided {@code combiner} function. + * @throws NullPointerException if mapper is null. * * @see #entriesToMap() * @see #entriesToMap(BinaryOperator) @@ -285,7 +288,7 @@ private MoreCollectors() { * defined by {@code mapSupplier} function * whose keys and values are taken from {@code Map.Entry} * @throws IllegalStateException if this stream contains duplicate keys - * (according to {@link Object#equals(Object)}) + * (according to {@link Object#equals(Object)}). * * @see #entriesToCustomMap(Function, Supplier) * @see #entriesToCustomMap(BinaryOperator, Supplier) @@ -314,7 +317,8 @@ private MoreCollectors() { * from {@code Map.Entry} and values are the result of applying * the provided {@code valueMapper} function to {@code Map.Entry} values. * @throws IllegalStateException if this stream contains duplicate keys - * (according to {@link Object#equals(Object)}) + * (according to {@link Object#equals(Object)}). + * @throws NullPointerException if mapper is null. * * @see #entriesToCustomMap(Supplier) * @see #entriesToCustomMap(BinaryOperator, Supplier) @@ -385,6 +389,7 @@ private MoreCollectors() { * @return {@code Collector} which collects elements into a {@code Map} * whose keys and values are taken from {@code Map.Entry} and combining them * using the {@code combiner} function + * @throws NullPointerException if mapper is null. * * @see #entriesToCustomMap(Supplier) * @see #entriesToCustomMap(Function, Supplier) diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 7cdc1bee..83c55f24 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -626,12 +626,12 @@ public void testEntriesToMap() { @Test public void testEntriesToMapWithCombiner() { streamEx(() -> Stream.of( - EntryStream.of(1, "*").toMap(), - EntryStream.of(1, "*", 2, "*").toMap(), - EntryStream.of(1, "*", 2, "*", 3, "*").toMap(), - EntryStream.of(1, "*", 2, "*", 3, "*", 4, "*").toMap(), - EntryStream.of(1, "*", 2, "*", 3, "*", 4, "*", 5, "*").toMap()) - .flatMap(map -> map.entrySet().stream()), supplier -> { + EntryStream.of(1, "*"), + EntryStream.of(1, "*", 2, "*"), + EntryStream.of(1, "*", 2, "*", 3, "*"), + EntryStream.of(1, "*", 2, "*", 3, "*", 4, "*"), + EntryStream.of(1, "*", 2, "*", 3, "*", 4, "*", 5, "*")) + .flatMap(Function.identity()), supplier -> { Map result = supplier.get().collect(MoreCollectors.entriesToMap(String::concat)); assertEquals("*****", result.get(1)); assertEquals("****", result.get(2)); @@ -641,10 +641,10 @@ public void testEntriesToMapWithCombiner() { }); streamEx(() -> Stream.of( - EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four").toMap(), - EntryStream.of(1, "ein", 2, "zwei", 3, "drei").toMap(), - EntryStream.of(1, "une", 2, "deux").toMap()) - .flatMap(map -> map.entrySet().stream()), supplier -> { + EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), + EntryStream.of(1, "ein", 2, "zwei", 3, "drei"), + EntryStream.of(1, "une", 2, "deux")) + .flatMap(Function.identity()), supplier -> { Map result = supplier.get().collect(MoreCollectors.entriesToMap((left, right) -> left + "," + right)); assertEquals("one,ein,une", result.get(1)); assertEquals("two,zwei,deux", result.get(2)); @@ -658,6 +658,8 @@ public void testEntriesToMapWithCombiner() { */ @Test public void testEntriesToMapWithValueMapper() { + Function nullFunction = null; + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(nullFunction)); streamEx(() -> EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), supplier -> { Map result = supplier.get().collect(MoreCollectors.entriesToMap((value) -> "See #" + value)); @@ -684,12 +686,13 @@ public void testEntriesToMapWithValueMapper() { @Test public void testEntriesToMapWithValueMapperAndCombiner() { assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(null, null)); + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(null, (a, b) -> a)); streamEx(() -> Stream.of( - EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four").toMap(), - EntryStream.of(1, "ein", 2, "zwei", 3, "drei").toMap(), - EntryStream.of(1, "une", 2, "deux").toMap()) - .flatMap(map -> map.entrySet().stream()), supplier -> { + EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), + EntryStream.of(1, "ein", 2, "zwei", 3, "drei"), + EntryStream.of(1, "une", 2, "deux")) + .flatMap(Function.identity()), supplier -> { Map result = supplier.get().collect( MoreCollectors.entriesToMap((value) -> "['" + value + "']", (left, right) -> left + ", " + right)); assertEquals("['one'], ['ein'], ['une']", result.get(1)); @@ -750,6 +753,9 @@ public void testEntriesToCustomMap() { */ @Test public void testEntriesToCustomMapWithValueMapper() { + Function nullFunction = null; + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(nullFunction, LinkedHashMap::new)); + assertThrows(IllegalStateException.class, () -> EntryStream.generate(() -> "a", () -> 1).limit(10).collect( MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", LinkedHashMap::new))); @@ -774,10 +780,10 @@ public void testEntriesToCustomMapWithValueMapper() { @Test public void testEntriesToCustomMapWithCombiner() { streamEx(() -> Stream.of( - EntryStream.of(100, "hundred", 2, "two", 3, "three", 4, "four").toMap(), - EntryStream.of(100, "hundert", 2, "zwei", 3, "drei").toMap(), - EntryStream.of(100, "cent", 2, "deux").toMap()) - .flatMap(map -> map.entrySet().stream()), supplier -> { + EntryStream.of(100, "hundred", 2, "two", 3, "three", 4, "four"), + EntryStream.of(100, "hundert", 2, "zwei", 3, "drei"), + EntryStream.of(100, "cent", 2, "deux")) + .flatMap(Function.identity()), supplier -> { NavigableMap result = supplier.get().collect( MoreCollectors.entriesToCustomMap((left, right) -> left + " -> " + right, TreeMap::new)); assertEquals("hundred -> hundert -> cent", result.get(100)); @@ -792,12 +798,12 @@ public void testEntriesToCustomMapWithCombiner() { }); streamEx(() -> Stream.of( - EntryStream.of(10, "*").toMap(), - EntryStream.of(10, "*", 2, "*").toMap(), - EntryStream.of(10, "*", 2, "*", 100, "*").toMap(), - EntryStream.of(10, "*", 2, "*", 100, "*", 4, "*").toMap(), - EntryStream.of(10, "*", 2, "*", 100, "*", 4, "*", 5, "*").toMap()) - .flatMap(map -> map.entrySet().stream()), supplier -> { + EntryStream.of(10, "*"), + EntryStream.of(10, "*", 2, "*"), + EntryStream.of(10, "*", 2, "*", 100, "*"), + EntryStream.of(10, "*", 2, "*", 100, "*", 4, "*"), + EntryStream.of(10, "*", 2, "*", 100, "*", 4, "*", 5, "*")) + .flatMap(Function.identity()), supplier -> { NavigableMap result = supplier.get().collect( MoreCollectors.entriesToCustomMap((left, right) -> left + " -> " + right, TreeMap::new)); @@ -811,12 +817,15 @@ public void testEntriesToCustomMapWithCombiner() { @Test public void testEntriesToCustomMapWithValueMapperAndCombiner() { assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, null, null)); + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, (a, b) -> a, null)); + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, null, TreeMap::new)); + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, (a, b) -> a, TreeMap::new)); streamEx(() -> Stream.of( - EntryStream.of(100, "hundred", 2, "two", 3, "three", 4, "four").toMap(), - EntryStream.of(100, "hundert", 2, "zwei", 3, "drei").toMap(), - EntryStream.of(100, "cent", 2, "deux").toMap()) - .flatMap(map -> map.entrySet().stream()), supplier -> { + EntryStream.of(100, "hundred", 2, "two", 3, "three", 4, "four"), + EntryStream.of(100, "hundert", 2, "zwei", 3, "drei"), + EntryStream.of(100, "cent", 2, "deux")) + .flatMap(Function.identity()), supplier -> { NavigableMap result = supplier.get().collect( MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", (left, right) -> left + ", " + right, TreeMap::new)); assertEquals("['hundred'], ['hundert'], ['cent']", result.get(100)); From de3ed50a30b52c83754a9dff6f7156cd5f040f47 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Mon, 15 Jun 2020 14:44:41 +0300 Subject: [PATCH 28/29] Apply code review points - Apply PECS signature to all new methods - Test new signature adaption --- .../one/util/streamex/MoreCollectors.java | 18 +-- .../one/util/streamex/MoreCollectorsTest.java | 120 ++++++++++++------ 2 files changed, 92 insertions(+), 46 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 3f5fe0ef..6730de4e 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -186,7 +186,7 @@ private MoreCollectors() { * @see Collectors#toMap(Function, Function) * @since 0.7.3 */ - public static Collector, ?, Map> entriesToMap() { + public static Collector, ?, Map> entriesToMap() { return Collectors.toMap(Entry::getKey, Entry::getValue); } @@ -214,7 +214,8 @@ private MoreCollectors() { * @see Collectors#toMap(Function, Function, BinaryOperator) * @since 0.7.3 */ - public static Collector, ?, Map> entriesToMap(BinaryOperator combiner) { + public static Collector, ?, Map> entriesToMap( + BinaryOperator combiner) { return Collectors.toMap(Entry::getKey, Entry::getValue, combiner); } @@ -240,7 +241,8 @@ private MoreCollectors() { * @see Collectors#toMap(Function, Function) * @since 0.7.3 */ - public static Collector, ?, Map> entriesToMap(Function valueMapper) { + public static Collector, ?, Map> entriesToMap( + Function valueMapper) { Objects.requireNonNull(valueMapper); return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue())); } @@ -270,7 +272,7 @@ private MoreCollectors() { * @see Collectors#toMap(Function, Function, BinaryOperator) * @since 0.7.3 */ - public static Collector, ?, Map> entriesToMap( + public static Collector, ?, Map> entriesToMap( Function valueMapper, BinaryOperator combiner) { Objects.requireNonNull(valueMapper); return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), combiner); @@ -296,7 +298,7 @@ private MoreCollectors() { * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) * @since 0.7.3 */ - public static > Collector, ?, M> entriesToCustomMap( + public static > Collector, ?, M> entriesToCustomMap( Supplier mapSupplier) { return Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), mapSupplier); } @@ -326,7 +328,7 @@ private MoreCollectors() { * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) * @since 0.7.3 */ - public static > Collector, ?, M> entriesToCustomMap( + public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), throwingMerger(), mapSupplier); @@ -360,7 +362,7 @@ private MoreCollectors() { * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) * @since 0.7.3 */ - public static > Collector, ?, M> entriesToCustomMap( + public static > Collector, ?, M> entriesToCustomMap( BinaryOperator combiner, Supplier mapSupplier) { return Collectors.toMap(Entry::getKey, Entry::getValue, combiner, mapSupplier); } @@ -397,7 +399,7 @@ private MoreCollectors() { * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) * @since 0.7.3 */ - public static > Collector, ?, M> entriesToCustomMap( + public static > Collector, ?, M> entriesToCustomMap( Function valueMapper, BinaryOperator combiner, Supplier mapSupplier) { Objects.requireNonNull(valueMapper); return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), combiner, mapSupplier); diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index 83c55f24..afd65bbb 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -603,6 +603,11 @@ public void testEntriesToMap() { EntryStream.generate(() -> "a", () -> 1).limit(10).collect(MoreCollectors.entriesToMap())); checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToMap()); + { + Map expected = Collections.emptyMap().entrySet().stream() + .collect(MoreCollectors.entriesToMap()); + assertTrue(expected.isEmpty()); + } { Map expected = EntryStream.of(1, "*", 2, "**", 3, "***", 4, "****", 5, "*****").toMap(); @@ -610,7 +615,7 @@ public void testEntriesToMap() { checkCollector("entriesToMap", expected, stream, MoreCollectors.entriesToMap()); streamEx(stream, supplier -> { - Map result = supplier.get().collect(MoreCollectors.entriesToMap()); + Map result = supplier.get().collect(MoreCollectors.entriesToMap()); assertEquals("*", result.get(1)); assertEquals("**", result.get(2)); assertEquals("***", result.get(3)); @@ -620,11 +625,54 @@ public void testEntriesToMap() { } } + + /** + * See {@link MoreCollectors#entriesToMap(Function)}. + */ + @Test + public void testEntriesToMapWithValueMapper() { + Function nullValueMapper = null; + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(nullValueMapper)); + assertThrows(IllegalStateException.class, () -> EntryStream.generate(() -> "a", () -> 1).limit(10) + .collect(MoreCollectors.entriesToMap((value) -> "['" + value + "']"))); + + checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToMap((a, b) -> a)); + + streamEx(() -> EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), + supplier -> { + Map result = supplier.get().collect(MoreCollectors.entriesToMap((value) -> "See #" + value)); + assertEquals("See #one", result.get(1)); + assertEquals("See #two", result.get(2)); + assertEquals("See #three", result.get(3)); + assertEquals("See #four", result.get(4)); + }); + + streamEx(() -> StreamEx.of("Bran Stark", "Arya Stark", "Jon Snow", "Tyrion (The Imp) Lannister", "Theon Greyjoy", + "Ser Jaime (The Kingslayer) Lannister", "Daenerys Stormborn Targaryen", "Khal Drogo", "Ser Jorah Mormont") + .mapToEntry(name -> name.contains("Khal") || name.contains("Ser")), supplier -> { + Map result = supplier.get().collect( + MoreCollectors.entriesToMap((value) -> value ? "This character has celebrity title" : "Standard character")); + assertEquals("This character has celebrity title", result.get("Khal Drogo")); + assertEquals("Standard character", result.get("Jon Snow")); + assertEquals("This character has celebrity title", result.get("Ser Jorah Mormont")); + }); + } + /** * See {@link MoreCollectors#entriesToMap(BinaryOperator)}. */ @Test public void testEntriesToMapWithCombiner() { + BinaryOperator nullCombiner = null; + assertThrows(NullPointerException.class, () -> EntryStream.of(1, "*").stream().collect(MoreCollectors.entriesToMap(nullCombiner))); + + checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToMap(String::concat)); + { + Map expected = Collections.emptyMap().entrySet().stream() + .collect(MoreCollectors.entriesToMap((a, b) -> b)); + assertTrue(expected.isEmpty()); + } + streamEx(() -> Stream.of( EntryStream.of(1, "*"), EntryStream.of(1, "*", 2, "*"), @@ -645,7 +693,7 @@ public void testEntriesToMapWithCombiner() { EntryStream.of(1, "ein", 2, "zwei", 3, "drei"), EntryStream.of(1, "une", 2, "deux")) .flatMap(Function.identity()), supplier -> { - Map result = supplier.get().collect(MoreCollectors.entriesToMap((left, right) -> left + "," + right)); + Map result = supplier.get().collect(MoreCollectors.entriesToMap((left, right) -> left + "," + right)); assertEquals("one,ein,une", result.get(1)); assertEquals("two,zwei,deux", result.get(2)); assertEquals("three,drei", result.get(3)); @@ -653,33 +701,6 @@ public void testEntriesToMapWithCombiner() { }); } - /** - * See {@link MoreCollectors#entriesToMap(Function)}. - */ - @Test - public void testEntriesToMapWithValueMapper() { - Function nullFunction = null; - assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(nullFunction)); - streamEx(() -> EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), - supplier -> { - Map result = supplier.get().collect(MoreCollectors.entriesToMap((value) -> "See #" + value)); - assertEquals("See #one", result.get(1)); - assertEquals("See #two", result.get(2)); - assertEquals("See #three", result.get(3)); - assertEquals("See #four", result.get(4)); - }); - - streamEx(() -> StreamEx.of("Bran Stark", "Arya Stark", "Jon Snow", "Tyrion (The Imp) Lannister", "Theon Greyjoy", - "Ser Jaime (The Kingslayer) Lannister", "Daenerys Stormborn Targaryen", "Khal Drogo", "Ser Jorah Mormont") - .mapToEntry(name -> name.contains("Khal") || name.contains("Ser")), supplier -> { - Map result = supplier.get().collect( - MoreCollectors.entriesToMap((value) -> value ? "This character has celebrity title" : "Standard character")); - assertEquals("This character has celebrity title", result.get("Khal Drogo")); - assertEquals("Standard character", result.get("Jon Snow")); - assertEquals("This character has celebrity title", result.get("Ser Jorah Mormont")); - }); - } - /** * See {@link MoreCollectors#entriesToMap(Function, BinaryOperator)}. */ @@ -687,13 +708,16 @@ public void testEntriesToMapWithValueMapper() { public void testEntriesToMapWithValueMapperAndCombiner() { assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(null, null)); assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(null, (a, b) -> a)); + BinaryOperator nullCombiner = null; + assertThrows(NullPointerException.class, () -> EntryStream.of(1, "*").stream().collect( + MoreCollectors.entriesToMap(Function.identity(), nullCombiner))); streamEx(() -> Stream.of( EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), EntryStream.of(1, "ein", 2, "zwei", 3, "drei"), EntryStream.of(1, "une", 2, "deux")) .flatMap(Function.identity()), supplier -> { - Map result = supplier.get().collect( + Map result = supplier.get().collect( MoreCollectors.entriesToMap((value) -> "['" + value + "']", (left, right) -> left + ", " + right)); assertEquals("['one'], ['ein'], ['une']", result.get(1)); assertEquals("['two'], ['zwei'], ['deux']", result.get(2)); @@ -721,13 +745,19 @@ public void testEntriesToCustomMap() { checkCollectorEmpty("entriesToMap", Collections.emptySortedMap(), MoreCollectors.entriesToCustomMap(LinkedHashMap::new)); + { + Map expected = Collections.emptyMap().entrySet().stream() + .collect(MoreCollectors.entriesToCustomMap(TreeMap::new)); + assertTrue(expected.isEmpty()); + } + { Map expected = EntryStream.of(5, "*****", 1, "*", 4, "****", 2, "**", 3, "***").toMap(); Supplier>> stream = expected.entrySet()::stream; checkCollector("entriesToMap", expected, stream, MoreCollectors.entriesToCustomMap(TreeMap::new)); streamEx(stream, supplier -> { - NavigableMap result = supplier.get().collect(MoreCollectors.entriesToCustomMap(TreeMap::new)); + NavigableMap result = supplier.get().collect(MoreCollectors.entriesToCustomMap(TreeMap::new)); assertEquals("*", result.get(1)); assertEquals("**", result.get(2)); assertEquals("***", result.get(3)); @@ -753,12 +783,12 @@ public void testEntriesToCustomMap() { */ @Test public void testEntriesToCustomMapWithValueMapper() { - Function nullFunction = null; - assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(nullFunction, LinkedHashMap::new)); + Function nullValueMapper = null; + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(nullValueMapper, LinkedHashMap::new)); + assertThrows(IllegalStateException.class, () -> EntryStream.generate(() -> "a", () -> 1).limit(10) + .collect(MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", LinkedHashMap::new))); - assertThrows(IllegalStateException.class, () -> - EntryStream.generate(() -> "a", () -> 1).limit(10).collect( - MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", LinkedHashMap::new))); + checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToCustomMap((a, b) -> a, TreeMap::new)); streamEx(() -> EntryStream.of(5, "*****", 1, "*", 4, "****", 2, "**", 3, "***"), supplier -> { NavigableMap result = supplier.get().collect( @@ -779,6 +809,16 @@ public void testEntriesToCustomMapWithValueMapper() { */ @Test public void testEntriesToCustomMapWithCombiner() { + BinaryOperator nullCombiner = null; + assertThrows(NullPointerException.class, () -> EntryStream.of(1, "*").stream().collect(MoreCollectors.entriesToCustomMap(nullCombiner, TreeMap::new))); + + checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToCustomMap(String::concat, TreeMap::new)); + { + Map expected = Collections.emptyMap().entrySet().stream() + .collect(MoreCollectors.entriesToCustomMap((a, b) -> b, TreeMap::new)); + assertTrue(expected.isEmpty()); + } + streamEx(() -> Stream.of( EntryStream.of(100, "hundred", 2, "two", 3, "three", 4, "four"), EntryStream.of(100, "hundert", 2, "zwei", 3, "drei"), @@ -805,7 +845,7 @@ public void testEntriesToCustomMapWithCombiner() { EntryStream.of(10, "*", 2, "*", 100, "*", 4, "*", 5, "*")) .flatMap(Function.identity()), supplier -> { - NavigableMap result = supplier.get().collect( + NavigableMap result = supplier.get().collect( MoreCollectors.entriesToCustomMap((left, right) -> left + " -> " + right, TreeMap::new)); assertEquals("2=* -> * -> * -> *", result.entrySet().iterator().next().toString()); }); @@ -820,13 +860,17 @@ public void testEntriesToCustomMapWithValueMapperAndCombiner() { assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, (a, b) -> a, null)); assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, null, TreeMap::new)); assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, (a, b) -> a, TreeMap::new)); + assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(null, (a, b) -> a, TreeMap::new)); + BinaryOperator nullCombiner = null; + assertThrows(NullPointerException.class, () -> EntryStream.of(1, "*").stream().collect( + MoreCollectors.entriesToCustomMap(Function.identity(), nullCombiner, TreeMap::new))); streamEx(() -> Stream.of( EntryStream.of(100, "hundred", 2, "two", 3, "three", 4, "four"), EntryStream.of(100, "hundert", 2, "zwei", 3, "drei"), EntryStream.of(100, "cent", 2, "deux")) .flatMap(Function.identity()), supplier -> { - NavigableMap result = supplier.get().collect( + NavigableMap result = supplier.get().collect( MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", (left, right) -> left + ", " + right, TreeMap::new)); assertEquals("['hundred'], ['hundert'], ['cent']", result.get(100)); assertEquals("['two'], ['zwei'], ['deux']", result.get(2)); From d06c067d7e87b1fecd5af3e33fae39af9349e630 Mon Sep 17 00:00:00 2001 From: Dzmitry Marudau Date: Mon, 15 Jun 2020 14:55:19 +0300 Subject: [PATCH 29/29] Apply code review points - Omit valueMapper overloads --- .../one/util/streamex/MoreCollectors.java | 65 ------------------- .../one/util/streamex/MoreCollectorsTest.java | 59 ----------------- 2 files changed, 124 deletions(-) diff --git a/src/main/java/one/util/streamex/MoreCollectors.java b/src/main/java/one/util/streamex/MoreCollectors.java index 6730de4e..7a05311d 100644 --- a/src/main/java/one/util/streamex/MoreCollectors.java +++ b/src/main/java/one/util/streamex/MoreCollectors.java @@ -181,7 +181,6 @@ private MoreCollectors() { * (according to {@link Object#equals(Object)}). * * @see #entriesToMap(BinaryOperator) - * @see #entriesToMap(Function) * @see #entriesToMap(Function, BinaryOperator) * @see Collectors#toMap(Function, Function) * @since 0.7.3 @@ -209,7 +208,6 @@ private MoreCollectors() { * using the {@code combiner} function * * @see #entriesToMap() - * @see #entriesToMap(Function) * @see #entriesToMap(Function, BinaryOperator) * @see Collectors#toMap(Function, Function, BinaryOperator) * @since 0.7.3 @@ -219,34 +217,6 @@ private MoreCollectors() { return Collectors.toMap(Entry::getKey, Entry::getValue, combiner); } - /** - * Returns a {@code Collector} that accumulates elements into a {@code Map} - * whose keys are taken from {@code Map.Entry} and values are the result - * of applying the provided {@code valueMapper} function. - * - * @param the {@link Comparable} type of then map keys - * @param the type of the map values - * @param the output type of the value mapping function - * @param valueMapper a mapping function to produce values from {@code Map.Entry} values - * @return {@code Collector} which collects elements into a {@code Map} - * whose keys are taken from {@code Map.Entry} and values are the result of applying - * the provided {@code valueMapper} function to {@code Map.Entry} values. - * @throws IllegalStateException if this stream contains duplicate keys - * (according to {@link Object#equals(Object)}). - * @throws NullPointerException if mapper is null. - * - * @see #entriesToMap() - * @see #entriesToMap(BinaryOperator) - * @see #entriesToMap(Function, BinaryOperator) - * @see Collectors#toMap(Function, Function) - * @since 0.7.3 - */ - public static Collector, ?, Map> entriesToMap( - Function valueMapper) { - Objects.requireNonNull(valueMapper); - return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue())); - } - /** * Returns a {@code Collector} that accumulates input elements into a {@code Map} * whose keys are taken from {@code Map.Entry} and values are the result @@ -268,7 +238,6 @@ private MoreCollectors() { * * @see #entriesToMap() * @see #entriesToMap(BinaryOperator) - * @see #entriesToMap(Function) * @see Collectors#toMap(Function, Function, BinaryOperator) * @since 0.7.3 */ @@ -292,7 +261,6 @@ private MoreCollectors() { * @throws IllegalStateException if this stream contains duplicate keys * (according to {@link Object#equals(Object)}). * - * @see #entriesToCustomMap(Function, Supplier) * @see #entriesToCustomMap(BinaryOperator, Supplier) * @see #entriesToCustomMap(Function, BinaryOperator, Supplier) * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) @@ -303,37 +271,6 @@ private MoreCollectors() { return Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), mapSupplier); } - /** - * Returns a {@code Collector} that accumulates elements into - * a result {@code Map} defined by {@code mapSupplier} function - * whose keys are taken from {@code Map.Entry} and values are the result - * of applying the provided {@code valueMapper} function. - * - * @param the {@link Comparable} type of then map keys - * @param the type of the map values - * @param the output type of the value mapping function - * @param the type of the resulting {@code Map} - * @param valueMapper a mapping function to produce values from {@code Map.Entry} values - * @return {@code Collector} which collects elements into a {@code Map} - * defined by {@code mapSupplier} function whose keys are taken - * from {@code Map.Entry} and values are the result of applying - * the provided {@code valueMapper} function to {@code Map.Entry} values. - * @throws IllegalStateException if this stream contains duplicate keys - * (according to {@link Object#equals(Object)}). - * @throws NullPointerException if mapper is null. - * - * @see #entriesToCustomMap(Supplier) - * @see #entriesToCustomMap(BinaryOperator, Supplier) - * @see #entriesToCustomMap(Function, BinaryOperator, Supplier) - * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) - * @since 0.7.3 - */ - public static > Collector, ?, M> entriesToCustomMap( - Function valueMapper, Supplier mapSupplier) { - Objects.requireNonNull(valueMapper); - return Collectors.toMap(Entry::getKey, entry -> valueMapper.apply(entry.getValue()), throwingMerger(), mapSupplier); - } - /** * Returns a {@code Collector} that accumulates elements into * a result {@code Map} defined by {@code mapSupplier} function @@ -357,7 +294,6 @@ private MoreCollectors() { * using the {@code combiner} function * * @see #entriesToCustomMap(Supplier) - * @see #entriesToCustomMap(Function, Supplier) * @see #entriesToCustomMap(Function, BinaryOperator, Supplier) * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) * @since 0.7.3 @@ -394,7 +330,6 @@ private MoreCollectors() { * @throws NullPointerException if mapper is null. * * @see #entriesToCustomMap(Supplier) - * @see #entriesToCustomMap(Function, Supplier) * @see #entriesToCustomMap(BinaryOperator, Supplier) * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier) * @since 0.7.3 diff --git a/src/test/java/one/util/streamex/MoreCollectorsTest.java b/src/test/java/one/util/streamex/MoreCollectorsTest.java index afd65bbb..9fda63c6 100644 --- a/src/test/java/one/util/streamex/MoreCollectorsTest.java +++ b/src/test/java/one/util/streamex/MoreCollectorsTest.java @@ -625,39 +625,6 @@ public void testEntriesToMap() { } } - - /** - * See {@link MoreCollectors#entriesToMap(Function)}. - */ - @Test - public void testEntriesToMapWithValueMapper() { - Function nullValueMapper = null; - assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToMap(nullValueMapper)); - assertThrows(IllegalStateException.class, () -> EntryStream.generate(() -> "a", () -> 1).limit(10) - .collect(MoreCollectors.entriesToMap((value) -> "['" + value + "']"))); - - checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToMap((a, b) -> a)); - - streamEx(() -> EntryStream.of(1, "one", 2, "two", 3, "three", 4, "four"), - supplier -> { - Map result = supplier.get().collect(MoreCollectors.entriesToMap((value) -> "See #" + value)); - assertEquals("See #one", result.get(1)); - assertEquals("See #two", result.get(2)); - assertEquals("See #three", result.get(3)); - assertEquals("See #four", result.get(4)); - }); - - streamEx(() -> StreamEx.of("Bran Stark", "Arya Stark", "Jon Snow", "Tyrion (The Imp) Lannister", "Theon Greyjoy", - "Ser Jaime (The Kingslayer) Lannister", "Daenerys Stormborn Targaryen", "Khal Drogo", "Ser Jorah Mormont") - .mapToEntry(name -> name.contains("Khal") || name.contains("Ser")), supplier -> { - Map result = supplier.get().collect( - MoreCollectors.entriesToMap((value) -> value ? "This character has celebrity title" : "Standard character")); - assertEquals("This character has celebrity title", result.get("Khal Drogo")); - assertEquals("Standard character", result.get("Jon Snow")); - assertEquals("This character has celebrity title", result.get("Ser Jorah Mormont")); - }); - } - /** * See {@link MoreCollectors#entriesToMap(BinaryOperator)}. */ @@ -778,32 +745,6 @@ public void testEntriesToCustomMap() { } } - /** - * See {@link MoreCollectors#entriesToCustomMap(Function, Supplier)}. - */ - @Test - public void testEntriesToCustomMapWithValueMapper() { - Function nullValueMapper = null; - assertThrows(NullPointerException.class, () -> MoreCollectors.entriesToCustomMap(nullValueMapper, LinkedHashMap::new)); - assertThrows(IllegalStateException.class, () -> EntryStream.generate(() -> "a", () -> 1).limit(10) - .collect(MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", LinkedHashMap::new))); - - checkCollectorEmpty("entriesToMap", Collections.emptyMap(), MoreCollectors.entriesToCustomMap((a, b) -> a, TreeMap::new)); - - streamEx(() -> EntryStream.of(5, "*****", 1, "*", 4, "****", 2, "**", 3, "***"), supplier -> { - NavigableMap result = supplier.get().collect( - MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", TreeMap::new)); - assertEquals("1=['*']", result.firstEntry().toString()); - assertEquals("5=['*****']", result.lastEntry().toString()); - }); - - streamEx(() -> EntryStream.of(5, "*****", 1, "*", 4, "****", 2, "**", 3, "***"), supplier -> { - Map result = supplier.get().collect( - MoreCollectors.entriesToCustomMap((value) -> "['" + value + "']", LinkedHashMap::new)); - assertEquals("5=['*****']", result.entrySet().iterator().next().toString()); - }); - } - /** * See {@link MoreCollectors#entriesToCustomMap(BinaryOperator, Supplier)}. */