From 1785d6ad9e532d442682f843be8958c8855017c2 Mon Sep 17 00:00:00 2001 From: Ivan Hetman Date: Wed, 7 Oct 2020 12:21:55 +0300 Subject: [PATCH] Collectors.toMap (#515) Implement Collectors.toMap --- .../java/util/stream/TCollectors.java | 48 +++++++++++++++++++ .../java/util/stream/CollectorsTest.java | 23 +++++++++ 2 files changed, 71 insertions(+) diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectors.java b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectors.java index 543bd9359..5b356ea32 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectors.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/stream/TCollectors.java @@ -17,12 +17,16 @@ package org.teavm.classlib.java.util.stream; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; +import java.util.function.Function; import java.util.function.Supplier; +import org.teavm.classlib.java.util.TObjects; public final class TCollectors { private TCollectors() { @@ -69,4 +73,48 @@ public final class TCollectors { return TCollector.of(StringBuilder::new, accumulator, combiner, sb -> sb.insert(0, prefix).append(suffix).toString()); } + + public static TCollector> toMap(Function keyMapper, + Function valueMapper) { + return TCollector.of(HashMap::new, + (map, el) -> { + K k = keyMapper.apply(el); + V newV = TObjects.requireNonNull(valueMapper.apply(el)); + V oldV = map.putIfAbsent(k, newV); + if (oldV != null) { + throw new IllegalStateException( + "Key " + k + " corresponds to values " + oldV + " and " + newV); + } + }, + (m1, m2) -> { + for (Map.Entry e : m2.entrySet()) { + V newV = TObjects.requireNonNull(e.getValue()); + V oldV = m1.putIfAbsent(e.getKey(), newV); + if (oldV != null) { + throw new IllegalStateException( + "Key " + e.getKey() + " corresponds to values " + oldV + " and " + newV); + } + } + return m1; + }, + TCollector.Characteristics.IDENTITY_FINISH); + } + + public static TCollector> toMap(Function keyMapper, + Function valueMapper, BinaryOperator mergeFunction) { + return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); + } + + public static > TCollector toMap(Function keyMapper, + Function valueMapper, BinaryOperator mergeFunction, Supplier mapFactory) { + return TCollector.of(mapFactory, + (map, el) -> map.merge(keyMapper.apply(el), valueMapper.apply(el), mergeFunction), + (m1, m2) -> { + for (Map.Entry e : m2.entrySet()) { + m1.merge(e.getKey(), e.getValue(), mergeFunction); + } + return m1; + }, + TCollector.Characteristics.IDENTITY_FINISH); + } } diff --git a/tests/src/test/java/org/teavm/classlib/java/util/stream/CollectorsTest.java b/tests/src/test/java/org/teavm/classlib/java/util/stream/CollectorsTest.java index 9fef1929e..64c36d9cf 100644 --- a/tests/src/test/java/org/teavm/classlib/java/util/stream/CollectorsTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/util/stream/CollectorsTest.java @@ -18,9 +18,13 @@ package org.teavm.classlib.java.util.stream; import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.Test; import org.junit.runner.RunWith; @@ -55,4 +59,23 @@ public class CollectorsTest { Stream.of(1, 2, 3).collect(Collectors.toCollection(() -> c)); assertEquals(Arrays.asList(1, 2, 3), c); } + + @Test(expected = NullPointerException.class) + public void noNullsInToMap() { + Stream.of(1, 2, null).collect(Collectors.toMap(Function.identity(), Function.identity())); + } + + @Test(expected = IllegalStateException.class) + public void noDuplicatesInToMap() { + Stream.of(1, 2, 2).collect(Collectors.toMap(Function.identity(), Function.identity())); + } + + @Test + public void toMap() { + Map expected = new HashMap<>(); + IntStream.range(1, 4).forEach(i -> expected.put(i, i)); + + assertEquals(expected, + IntStream.range(1, 4).boxed().collect(Collectors.toMap(Function.identity(), Function.identity()))); + } }