1717package org .springframework .util ;
1818
1919import java .util .EnumSet ;
20- import java .util .HashMap ;
20+ import java .util .LinkedHashMap ;
2121import java .util .List ;
2222import java .util .Map .Entry ;
2323import java .util .Set ;
2828import java .util .stream .Collector ;
2929
3030/**
31- * A {@link Collector} for building a {@link MultiValueMap} from a {@link java.util.stream.Stream}.
32- * <br/>
33- * Moved from {@code org.springframework.data.util.MultiValueMapCollector}.
31+ * A {@link Collector} for building a {@link MultiValueMap} from a
32+ * {@link java.util.stream.Stream Stream}.
3433 *
35- * @author Jens Schauder
34+ * <p>Copied from the Spring Data Commons project.
3635 *
37- * @param <T> – the type of input elements to the reduction operation
38- * @param <K> – the type of the key elements
39- * @param <V> – the type of the value elements
36+ * @author Jens Schauder
37+ * @author Florian Hof
38+ * @author Sam Brannen
39+ * @since 7.0.2
40+ * @param <T> the type of input elements to the reduction operation
41+ * @param <K> the key type
42+ * @param <V> the value element type
4043 */
41- public class MultiValueMapCollector <T , K , V > implements Collector <T , MultiValueMap <K , V >, MultiValueMap <K , V >> {
44+ public final class MultiValueMapCollector <T , K , V > implements Collector <T , MultiValueMap <K , V >, MultiValueMap <K , V >> {
45+
4246private final Function <T , K > keyFunction ;
47+
4348private final Function <T , V > valueFunction ;
4449
45- public MultiValueMapCollector (Function <T , K > keyFunction , Function <T , V > valueFunction ) {
50+
51+ private MultiValueMapCollector (Function <T , K > keyFunction , Function <T , V > valueFunction ) {
4652this .keyFunction = keyFunction ;
4753this .valueFunction = valueFunction ;
4854}
4955
56+
57+ /**
58+ * Create a new {@code MultiValueMapCollector} from the given key and value
59+ * functions.
60+ * @param <T> the type of input elements to the reduction operation
61+ * @param <K> the key type
62+ * @param <V> the value element type
63+ * @param keyFunction a {@code Function} which converts an element of type
64+ * {@code T} to a key of type {@code K}
65+ * @param valueFunction a {@code Function} which converts an element of type
66+ * {@code T} to an element of type {@code V}; supply {@link Function#identity()}
67+ * if no conversion should be performed
68+ * @return a new {@code MultiValueMapCollector}
69+ * @see #indexingBy(Function)
70+ */
71+ public static <T , K , V > MultiValueMapCollector <T , K , V > of (Function <T , K > keyFunction , Function <T , V > valueFunction ) {
72+ return new MultiValueMapCollector <>(keyFunction , valueFunction );
73+ }
74+
75+ /**
76+ * Create a new {@code MultiValueMapCollector} using the given {@code indexer}.
77+ * <p>Delegates to {@link #of(Function, Function)}, supplying the given
78+ * {@code indexer} as the key function and {@link Function#identity()}
79+ * as the value function.
80+ * <p>For example, if you would like to collect the elements of a {@code Stream}
81+ * of strings into a {@link MultiValueMap} keyed by the lengths of the strings,
82+ * you could create such a {@link Collector} via
83+ * {@code MultiValueMapCollector.indexingBy(String::length)}.
84+ * @param <K> the key type
85+ * @param <V> the value element type
86+ * @param indexer a {@code Function} which converts a value of type {@code V}
87+ * to a key of type {@code K}
88+ * @return a new {@code MultiValueMapCollector} based on an {@code indexer}
89+ * @see #of(Function, Function)
90+ */
5091public static <K , V > MultiValueMapCollector <V , K , V > indexingBy (Function <V , K > indexer ) {
5192return new MultiValueMapCollector <>(indexer , Function .identity ());
5293}
5394
95+
5496@ Override
5597public Supplier <MultiValueMap <K , V >> supplier () {
56- return () -> CollectionUtils .toMultiValueMap (new HashMap <K , List <V >>());
98+ return () -> CollectionUtils .toMultiValueMap (new LinkedHashMap <K , List <V >>());
5799}
58100
59101@ Override
@@ -80,4 +122,5 @@ public Function<MultiValueMap<K, V>, MultiValueMap<K, V>> finisher() {
80122public Set <Characteristics > characteristics () {
81123return EnumSet .of (Characteristics .IDENTITY_FINISH , Characteristics .UNORDERED );
82124}
125+
83126}
0 commit comments