You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用putIfAbsent()操作流时遇UnsupportedOperationException问题排查

问题排查与解决方案

问题根源

抛出UnsupportedOperationException的核心原因及其他问题:

  • 不可修改Map:x.getTaskResults()返回的是不可修改的Map(比如通过Map.of()、Collections.unmodifiableMap()创建),调用putIfAbsent这类修改操作会直接触发异常。
  • 并行流线程不安全:用parallel()并行操作同一个Map,即使Map可修改,也会引发并发修改问题或数据不一致。
  • 条件逻辑错误:原代码allHistoryTasks.containsAll(x.getTaskResults().keySet())是判断x的任务结果包含所有历史任务,和需求“包含任意一个历史任务则补全”不符。

修复方案

  1. 创建新的可修改Map,避免修改原不可变Map;
  2. 移除并行流,改为普通循环或串行流,保证线程安全;
  3. 修正条件判断,检查x的任务结果是否包含任意一个历史任务。

修复后代码

private Set<String> allHistoryTasks = Set.of("Phalanxing", "Shieldwalling", "Tercioing", "Wedging");

public Map<Person, Map<String, Integer>> addHistoryIfPresent(Stream<CourseResult> stream) {
    return stream.collect(Collectors.toMap(
            CourseResult::getPerson,
            x -> {
                // 创建新的可修改HashMap,复制原任务结果
                Map<String, Integer> taskResults = new HashMap<>(x.getTaskResults());
                // 检查是否包含任意一个历史任务
                boolean hasHistoryTask = taskResults.keySet().stream()
                        .anyMatch(allHistoryTasks::contains);
                if (hasHistoryTask) {
                    // 补全所有历史任务,不存在则设为0
                    allHistoryTasks.forEach(task -> taskResults.putIfAbsent(task, 0));
                }
                return taskResults;
            }
    ));
}

额外说明

  • 用HashMap包装原Map,既保留原有数据,又支持修改操作;
  • 用anyMatch替代原错误的containsAll,符合“包含特定任务则补全”的需求;
  • 直接遍历allHistoryTasks集合,比转数组再用IntStream更简洁直观。

内容的提问来源于stack exchange,提问作者Oleh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 01:40:24