簡単に変換できますList<V>
into Map<K, List<V>>
。例えば:
public Map<Integer, List<String>> getMap(List<String> strings) {
return
strings.stream()
.collect(Collectors.groupingBy(String::length));
}
しかし、私は自分のList
とMap
suppliersでそれをやりたいです。
私はこれを思いつきました:
public Map<Integer, List<String>> getMap(List<String> strings) {
return strings.stream()
.collect(Collectors.toMap(
String::length,
item -> {List<String> list = new ArrayList<>(); list.add(item); return list;},
(list1, list2) -> {list1.addAll(list2); return list1;},
HashMap::new));
}
質問:より簡単、冗長、または効率的な方法がありますか?たとえば、次のようなもの(機能しません):
return strings.stream()
.collect(Collectors.toMap(
String::length,
ArrayList::new,
HashMap::new));
そして、List
サプライヤーを定義するだけで、Map
サプライヤーを定義する必要がない場合はどうなりますか?
次のものがあります。
_public Map<Integer, List<String>> getMap(List<String> strings) {
return strings.stream().collect(
Collectors.groupingBy(String::length, HashMap::new, Collectors.toCollection(ArrayList::new))
);
}
_
コレクター groupingBy(classifier, mapFactory, downstream)
を使用して、mapFactory
に必要なマップのサプライヤーを渡すことで、どのタイプのマップが必要かを指定できます。次に、同じキーにグループ化された要素を収集するために使用されるダウンストリームコレクタは toCollection(collectionFactory)
です。これにより、指定されたサプライヤから取得したコレクションに収集できます。
これにより、返されるマップがHashMap
になり、各値のリストがArrayList
になります。マップとコレクションの特定の実装を返したい場合は、メソッドがそれらの特定のタイプも返すようにしたいので、それらのプロパティを使用できることに注意してください。
コレクションサプライヤのみを指定し、groupingBy
デフォルトマップを保持する場合は、上記のコードでサプライヤを省略して two arguments overload を使用できます。
_public Map<Integer, List<String>> getMap(List<String> strings) {
return strings.stream().collect(
Collectors.groupingBy(String::length, Collectors.toCollection(ArrayList::new))
);
}
_
補足として、あなたはそのための一般的な方法を持つことができます:
_public <K, V, C extends Collection<V>, M extends Map<K, C>> M getMap(List<V> list,
Function<? super V, ? extends K> classifier, Supplier<M> mapSupplier, Supplier<C> collectionSupplier) {
return list.stream().collect(
Collectors.groupingBy(classifier, mapSupplier, Collectors.toCollection(collectionSupplier))
);
}
_
この宣言の利点は、これを使用して特定のHashMap
of ArrayList
sを結果として、またはLinkedHashMap
of LinkedLists
sを結果として使用できることです。それ:
_HashMap<Integer, ArrayList<String>> m = getMap(Arrays.asList("foo", "bar", "toto"),
String::length, HashMap::new, ArrayList::new);
LinkedHashMap<Integer, LinkedList<String>> m2 = getMap(Arrays.asList("foo", "bar", "toto"),
String::length, LinkedHashMap::new, LinkedList::new);
_
しかし、その時点で、コードでgroupingBy
を直接使用する方が簡単かもしれません...
同様の状況がありました。私はそれを次のように解決しました:
_Map<String, List<Object>> map = stringList.stream().collect(Collectors.toMap(str -> str, str -> populateList(str)));
_
populateList()
は次のとおりです。
_private List<Object> populateList(final String str) {
...
....
List<Object> list = // dao.get(str);
return list;
}
_