< prev index next >

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

Print this page

    rev 48045 : 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, jrose, 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} that accumulates the input elements into an
    +      * <a href="../List.html#unmodifiable">unmodifiable List</a> 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} that accumulates the input elements into an
    +      * <a href="../Set.html#unmodifiable">unmodifiable Set</a>
    +      * @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} 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
    +      * @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,1616 ----
                                          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} 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
    +      * @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 >