如何转换List< V>使用Java 8流以及自定义的List和Map供应商将其导入Map< K,List< V>中? [英] How to convert List<V> into Map<K, List<V>>, with Java 8 streams and custom List and Map suppliers?

查看:105
本文介绍了如何转换List< V>使用Java 8流以及自定义的List和Map供应商将其导入Map< K,List< V>中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

List<V>转换为Map<K, List<V>>很容易.例如:

It's easy to convert List<V> into Map<K, List<V>>. For example:

public Map<Integer, List<String>> getMap(List<String> strings) {
   return
      strings.stream()
             .collect(Collectors.groupingBy(String::length));
}

但是我想使用自己的ListMap 供应商.

But I want to do it with my own List and 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));
}

问题:是否有更简单,更详细或更有效的方法?例如,类似这样的东西(不起作用):

Question: Is there an easier, less verbose, or more efficient way of doing it? For example, something like this (which doesn't work):

return strings.stream()
      .collect(Collectors.toMap(
            String::length,
            ArrayList::new,                    
            HashMap::new));

如果我只需要定义List供应商,而不需要定义Map供应商怎么办?

And what if I only need to define the List supplier, but not the Map supplier?

推荐答案

您可能具有以下条件:

public Map<Integer, List<String>> getMap(List<String> strings) {
    return strings.stream().collect(
      Collectors.groupingBy(String::length, HashMap::new, Collectors.toCollection(ArrayList::new))
    );
}

收集器

The collector groupingBy(classifier, mapFactory, downstream) can be used to specify which type of map is wanted, by passing it a supplier of the wanted map for the mapFactory. Then, the downstream collector, which is used to collect elements grouped to the same key, is toCollection(collectionFactory), which enables to collect into a collection obtained from the given supplier.

这确保返回的映射是HashMap,并且每个值中的列表都是ArrayList.请注意,如果要返回map和collection的特定实现,则很可能希望该方法也返回那些特定的类型,以便可以使用它们的属性.

This makes sure that the map returned is a HashMap and that the lists, in each value, are ArrayList. Note that if you want to return specific implementations of map and collection, then you most likely want the method to return those specific types as well, so you can use their properties.

如果您只想指定集合供应商,并保留groupingBy默认映射,则只需在上面的代码中省略供应商,并使用

If you only want to specify a collection supplier, and keep groupingBy default map, you can just omit the supplier in the code above and use the two arguments overload:

public Map<Integer, List<String>> getMap(List<String> strings) {
    return strings.stream().collect(
      Collectors.groupingBy(String::length, Collectors.toCollection(ArrayList::new))
    );
}


作为旁注,您可以为此使用通用方法:


As a side-note, you could have a generic method for that:

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))
    );
}

此声明的优点在于,您现在可以使用它来声明ArrayList的特定HashMapLinkedListsLinkedHashMap(如果调用者希望的话):

The advantage with this declaration is that you can now use it to have specific HashMap of ArrayLists as result, or LinkedHashMap of LinkedListss, if the caller wishes it:

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可能会更简单...

but, at that point, it may be simpler to directly use the groupingBy in the code...

这篇关于如何转换List&lt; V&gt;使用Java 8流以及自定义的List和Map供应商将其导入Map&lt; K,List&lt; V&gt;中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆