java - 将列表值流式传输到 Map.Entry.values

标签 java lambda java-8 java-stream

我正在寻找一种方法 Stream一个List进入Map我可以在其中指定 key 。

例如,假设我有两个列表:

List<String> one = Arrays.asList("1","2","3");
List<String> two = Arrays.asList("100","200","300");

我正在寻找一种方法 Stream他们变成Map<String, List<String>>

{
  "below 100" : ["1","2","3"],
  "above 100" : ["100","200","300"]
}

非常感谢任何帮助。到目前为止,这是我想出的:

Stream.of(
  one.stream(),
      .collect(Collectors.toMap("below 100", ??)
  ,
  two.stream()
      .collect(Collectors.toMap("above 100", ??)
 )
 .reduce(Stream::concat)

最佳答案

我发现了两种类似的方法。在这两种方式中,我们分别将每个 List 转换为 Map>,然后连接两个 Map。第一个选项较短并使用内联收集器,而第二个选项创建一个新的收集器类。

对于这两个选项,我们首先声明列表:

    List<String> one = Arrays.asList("1", "2", "3");
    List<String> two = Arrays.asList("100", "200", "300");
  1. 带有内联收集器的更短选项:

    private BinaryOperator<List<String>> addToList() {
        return (list, str) -> {
            ((ArrayList<String>) list).addAll(str);
            return list;
        };
    }
    
    Map<String, List<String>> map = Stream.of(
            // first list
            one.stream()
                    .collect(Collectors.toMap(
                            l -> "below 100", 
                            // we need List as map value
                            l -> Stream.of(l).collect(Collectors.toList()), 
                            // merge function
                            addToList(), 
                            // provide HashMap for result 
                            HashMap::new 
                    // we can't stream collected Map directly, only through EntrySet
                    )).entrySet(),
            // second list
            two.stream()
                    .collect(Collectors.toMap(
                            l -> "above 100", 
                            l -> Stream.of(l).collect(Collectors.toList()),
                            addToList(), 
                            HashMap::new 
                    )).entrySet()
            )
            // extract Entry<String, List<String>> 
            .flatMap(entrySet -> entrySet.stream())
             // convert Entry<String, List<String>> to Map<String, List<String>
            .collect(Collectors.toMap(
                    entry -> entry.getKey(),
                    entry -> entry.getValue()));
    
  2. 使用自定义收集器的选项:

原始流代码较短,仅调用 ListToMapCollector 而不是实现内联收集器。

    Map<String, List<String>> map = Stream
            .of(
                    one.stream()
                            // use custom ListToMapCollector
                            .collect(new ListToMapCollector("below 100"))
                            // we can't stream collected Map directly, only through EntrySet
                            .entrySet(), 
                    two.stream()
                            .collect(new ListToMapCollector("above 100"))
                            .entrySet()) 
            // extract Entry<String, List<String>> 
            .flatMap(entrySet -> entrySet.stream())
             // convert Entry<String, List<String>> to Map<String, List<String>
            .collect(Collectors.toMap(
                    entry -> entry.getKey(),
                    entry -> entry.getValue()));

还有ListToMapCollector,我用了this tutorial创建时:

     public class ListToMapCollector implements Collector<String, Map<String, 
     List<String>>, Map<String, List<String>>>
    {
    private String mapKey;

    public TestCollector(String string)
    {
        this.mapKey = string;
    }

    @Override
    public Supplier<Map<String, List<String>>> supplier() {
        // provide HashMap for result
        return HashMap::new;
    }

    @Override
    public BiConsumer<Map<String, List<String>>, String> accumulator() {
        return (map, stringValue) -> {
            if (!map.containsKey(mapKey))
            {
                map.put(mapKey, new ArrayList<>());
            }
            map.get(mapKey).add(stringValue);
        };
    }

    @Override
    public BinaryOperator<Map<String, List<String>>> combiner() {
        // Needed for parrallel stream, excluded for brevity.
        return null;
    }

    @Override
    public Function<Map<String, List<String>>, Map<String, List<String>>> finisher() {
        return Function.identity();
    }

    @Override
    public Set<java.util.stream.Collector.Characteristics> characteristics() {
        return Collections.singleton(Characteristics.IDENTITY_FINISH);
    }
    }

关于java - 将列表值流式传输到 Map.Entry.values,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39168813/

相关文章:

c++ - 尝试将 c++ qsort 与内联函数一起使用

ssl - 从 Java 连接到 SSL 1.2 主机时出现问题 - 忽略 TLS v1 不支持的密码套件

java - Boolean.valueOf(String) 可以返回 null 吗?

c++ - 如何从嵌套的 lambda 表达式创建 Functor 类

C++11 g++ 奇怪(使用默认模板、lambda 和 remove_if)

Java 流 : Is there a cleaner way of doing this?

Java 8 流批处理

java - 如何在 Hibernate 中更新 TimerTask 中的实体

java - java中有没有办法限制一个包对其他包的可见性

java - 每月复利 Java 应用程序