< prev index next >
src/java.base/share/classes/java/util/stream/Collectors.java
Print this page
rev 47476 : 8177290: add copy factory methods for unmodifiable List, Set, Map
8184690: add Collectors for collecting into unmodifiable List, Set, and Map
Reviewed-by: alanb, dholmes, rriggs, scolebourne
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -114,10 +114,12 @@
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
static final Set<Collector.Characteristics> CH_UNORDERED_ID
= Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
Collector.Characteristics.IDENTITY_FINISH));
static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
+ static final Set<Collector.Characteristics> CH_UNORDERED_NOID
+ = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED));
private Collectors() { }
/**
* Construct an {@code IllegalStateException} with appropriate message.
@@ -277,10 +279,30 @@
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
/**
+ * Returns a {@code Collector} that accumulates the input elements into an
+ * <a href="List.html#unmodifiable">unmodifiable List</a> in encounter
+ * order. The returned Collector disallows null values and will throw
+ * {@code NullPointerException} if it is presented with a null value.
+ *
+ * @param <T> the type of the input elements
+ * @return a {@code Collector} which collects all the input elements into a
+ * {@code List}, in encounter order
+ * @since 10
+ */
+ @SuppressWarnings("unchecked")
+ public static <T>
+ Collector<T, ?, List<T>> toUnmodifiableList() {
+ return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
+ (left, right) -> { left.addAll(right); return left; },
+ list -> (List<T>)List.of(list.toArray()),
+ CH_NOID);
+ }
+
+ /**
* Returns a {@code Collector} that accumulates the input elements into a
* new {@code Set}. There are no guarantees on the type, mutability,
* serializability, or thread-safety of the {@code Set} returned; if more
* control over the returned {@code Set} is required, use
* {@link #toCollection(Supplier)}.
@@ -304,10 +326,40 @@
},
CH_UNORDERED_ID);
}
/**
+ * Returns a {@code Collector} that accumulates the input elements into an
+ * <a href="Set.html#unmodifiable">unmodifiable Set</a>. The returned
+ * Collector disallows null values and will throw {@code NullPointerException}
+ * if it is presented with a null value. Duplicate elements are allowed, in
+ * which case an arbitrary element of the duplicates is preserved.
+ *
+ * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
+ * Collector.
+ *
+ * @param <T> the type of the input elements
+ * @return a {@code Collector} which collects all the input elements into a
+ * {@code Set}
+ * @since 10
+ */
+ @SuppressWarnings("unchecked")
+ public static <T>
+ Collector<T, ?, Set<T>> toUnmodifiableSet() {
+ return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
+ (left, right) -> {
+ if (left.size() < right.size()) {
+ right.addAll(left); return right;
+ } else {
+ left.addAll(right); return left;
+ }
+ },
+ set -> (Set<T>)Set.of(set.toArray()),
+ CH_UNORDERED_NOID);
+ }
+
+ /**
* Returns a {@code Collector} that concatenates the input elements into a
* {@code String}, in encounter order.
*
* @return a {@code Collector} that concatenates the input elements into a
* {@code String}, in encounter order
@@ -1351,11 +1403,11 @@
* mapping functions to the input elements.
*
* <p>If the mapped keys contain duplicates (according to
* {@link Object#equals(Object)}), an {@code IllegalStateException} is
* thrown when the collection operation is performed. If the mapped keys
- * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
+ * might have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
* instead.
*
* <p>There are no guarantees on the type, mutability, serializability,
* or thread-safety of the {@code Map} returned.
*
@@ -1409,10 +1461,49 @@
uniqKeysMapMerger(),
CH_ID);
}
/**
+ * Returns a {@code Collector} that accumulates the input elements into an
+ * <a href="Map.html#unmodifiable">unmodifiable Map</a>,
+ * whose keys and values are the result of applying the provided
+ * mapping functions to the input elements.
+ *
+ * <p>If the mapped keys contain duplicates (according to
+ * {@link Object#equals(Object)}), an {@code IllegalStateException} is
+ * thrown when the collection operation is performed. If the mapped keys
+ * might have duplicates, use {@link #toUnmodifiableMap(Function, Function, BinaryOperator)}
+ * instead.
+ *
+ * <p>The returned Collector disallows null keys and values. If either mapping function
+ * returns null, {@code NullPointerException} will be thrown.
+ *
+ * @param <T> the type of the input elements
+ * @param <K> the output type of the key mapping function
+ * @param <U> the output type of the value mapping function
+ * @param keyMapper a mapping function to produce keys, must be non-null
+ * @param valueMapper a mapping function to produce values, must be non-null
+ * @return a {@code Collector} which collects elements into an unmodifiable {@code Map}
+ * whose keys and values are the result of applying mapping functions to
+ * the input elements
+ * @throws NullPointerException if either keyMapper or valueMapper is null
+ *
+ * @see #toUnmodifiableMap(Function, Function, BinaryOperator)
+ * @since 10
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public static <T, K, U>
+ Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
+ Function<? super T, ? extends U> valueMapper) {
+ Objects.requireNonNull(keyMapper);
+ Objects.requireNonNull(valueMapper);
+ return collectingAndThen(
+ toMap(keyMapper, valueMapper),
+ map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
+ }
+
+ /**
* Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided
* mapping functions to the input elements.
*
* <p>If the mapped
@@ -1471,10 +1562,57 @@
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction) {
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}
+
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into an
+ * <a href="Map.html#unmodifiable">unmodifiable Map</a>,
+ * whose keys and values are the result of applying the provided
+ * mapping functions to the input elements.
+ *
+ * <p>If the mapped
+ * keys contain 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 merging function.
+ *
+ * <p>The returned Collector disallows null keys and values. If either mapping function
+ * returns null, {@code NullPointerException} will be thrown.
+ *
+ * @param <T> the type of the input elements
+ * @param <K> the output type of the key mapping function
+ * @param <U> the output type of the value mapping function
+ * @param keyMapper a mapping function to produce keys, must be non-null
+ * @param valueMapper a mapping function to produce values, must be non-null
+ * @param mergeFunction a merge function, used to resolve collisions between
+ * values associated with the same key, as supplied
+ * to {@link Map#merge(Object, Object, BiFunction)},
+ * must be non-null
+ * @return a {@code Collector} which collects elements into an unmodifiable {@code Map}
+ * whose keys are the result of applying a key mapping function to the input
+ * elements, and whose values are the result of applying a value mapping
+ * function to all input elements equal to the key and combining them
+ * using the merge function
+ * @throws NullPointerException if the keyMapper, valueMapper, or mergeFunction is null
+ *
+ * @see #toUnmodifiableMap(Function, Function)
+ * @since 10
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public static <T, K, U>
+ Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
+ Function<? super T, ? extends U> valueMapper,
+ BinaryOperator<U> mergeFunction) {
+ Objects.requireNonNull(keyMapper);
+ Objects.requireNonNull(valueMapper);
+ Objects.requireNonNull(mergeFunction);
+ return collectingAndThen(
+ toMap(keyMapper, valueMapper, mergeFunction, HashMap::new),
+ map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
+ }
+
/**
* Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided
* mapping functions to the input elements.
*
< prev index next >