< prev index next >

src/java.base/share/classes/java/util/stream/Collectors.java

Print this page
rev 47479 : 8177290: add copy factory methods for unmodifiable List, Set, Map
8184690: add Collectors for collecting into unmodifiable List, Set, and Map
Reviewed-by: alanb, briangoetz, dholmes, rriggs, scolebourne

*** 1,7 **** /* ! * Copyright (c) 2012, 2016, 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 --- 1,7 ---- /* ! * 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,123 **** --- 114,125 ---- = 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,286 **** --- 279,308 ---- (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,313 **** --- 326,365 ---- }, 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. If the input contains duplicate elements, + * 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,1361 **** * 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)} * instead. * * <p>There are no guarantees on the type, mutability, serializability, * or thread-safety of the {@code Map} returned. * --- 1403,1413 ---- * 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 #toMap(Function, Function, BinaryOperator)} * instead. * * <p>There are no guarantees on the type, mutability, serializability, * or thread-safety of the {@code Map} returned. *
*** 1409,1418 **** --- 1461,1509 ---- 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)} + * to handle merging of the values. + * + * <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, "keyMapper"); + Objects.requireNonNull(valueMapper, "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,1480 **** --- 1562,1618 ---- 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, "keyMapper"); + Objects.requireNonNull(valueMapper, "valueMapper"); + Objects.requireNonNull(mergeFunction, "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 >