【问题标题】:how to update a Map<List<String>,List<String>> from Java's 8 Stream?如何从 Java 8 Stream 更新 Map<List<String>,List<String>>?
【发布时间】:2025-12-03 16:25:01
【问题描述】:

我想要完成的是在我的流映射中运行一个方法,基于如果返回正确,将其添加到成功列表中,该列表将进入集合的映射键,如果失败,它将被添加到集合值中的失败列表中:

        List<String> success = new ArrayList<>();
        List<String> failure = new ArrayList<>();
        Map<List<String>,List<String>> masterLista = new HashMap<>();
        masterLista.put(success, failure);

        masterLista = list.stream().map(l -> {
            String newS=serviceApi.getClearSongName(l);
            if(newS!=null){    
                //Here the return should update the sucess list
                return serviceApi.getClearSongName(l);
            } else{
                //Here the return should update the failure list
                return l;
            }
        }).collect(Collectors.toList());

实际上集合的映射不是必需的,我唯一想要的是在 Stream 的映射内部已经更新了成功和失败的两个列表,以避免在单个列表中进行进一步处理。

编辑:我正在使用流,因为实际上目标是使用 parallelStream

【问题讨论】:

  • 我只会使用 for 循环。
  • 另外,使用可变哈希映射键是一个非常糟糕的主意。
  • 看起来你真正想要的是Pair&lt;String, String&gt; 甚至可能是Seq&lt;Try&lt;String&gt;&gt; (Vavr)。
  • 不确定在这种情况下为什么需要 HashMap。我想你误解了地图的使用
  • 只需使用普通的 for 循环或 for-each 循环。为什么需要在这里使用 Streams?它是一个简单的 for 循环列表,其中包含 if-else,并根据条件将列表元素添加为成功或失败。

标签: java java-8 java-stream


【解决方案1】:

您不需要Map,甚至不需要Stream。一个简单的for 循环就可以完成这项工作,如果您愿意,也可以使用List::forEach

for循环

for (String str : list) {
    String newS = serviceApi.getClearSongName(str);
    if (newS != null)
        success.add(newS);
    else
        failure.add(newS);
}

Foreach

list.forEach(str -> {
    String newS = serviceApi.getClearSongName(str);
    if (newS != null)
        success.add(newS);
    else
        failure.add(newS);
});

分区方式

您也可以使用Collector::partitioningBy,它返回Map&lt;Boolean, List&lt;String&gt;&gt;

Map<Boolean, List<String>> map = 
    list.stream()
        .collect(Collectors.partitioningBy(str -> serviceApi.getClearSongName(str) != null));

map.get(true) 将返回在您的逻辑中分类为 ass success 的那些

【讨论】:

    【解决方案2】:

    我猜您需要流式传输列表,调用 api 并分别收集成功和失败。下面是一个关于如何做到这一点的小 sn-p(它在 groovy 中而不是 java 中)

    def a = [1,2,3,4,5,6,7,8,9]
    Map<Boolean,List> x = a.stream().map{it -> new Tuple2<Boolean,Integer>(it>5, it)}.collect(Collectors.partitioningBy{i -> i[0]})
    println(x)
    

    Collectors.partitionBy 根据谓词(条件)将流分成两组。如果您需要分成多个组,请使用 Collectors.groupingBy() 方法。以下链接包含有关此特定用例的更多详细信息 Can you split a stream into two streams?

    请注意“无法在无限流上工作”警告

    您的代码如下所示

    Map<Boolean,List> masterLista = list.stream()
    .map(l -> {
                    String newS=serviceApi.getClearSongName(l)
                    return new Tuple2<Boolean,String>(newS!=null, l)
    
    }).collect(Collectors.partitioningBy{i -> i[0]})
    

    【讨论】:

      最近更新 更多