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

调用Set的addAll方法抛出UnsupportedOperationException问题分析

问题分析:调用Set.addAll()抛出UnsupportedOperationException

问题重现

原代码尝试合并两个Set集合时抛出异常:

Set<String> allNumbersSet = customerInfoService.getCustomerPhoneNumbers(bankCustomerId);
additionalInformation
        .map(info -> info.get(BANK_PE_CUSTOMER_ID_KEY))
        .filter(StringUtils::isNotEmpty)
        .ifPresent(id -> allNumbersSet.addAll(customerInfoService.getCustomerPhoneNumbers(id))); // 此处报错

getCustomerPhoneNumbers方法实现:

@Override
public Set<String> getCustomerPhoneNumbers(String customerId) {
    return backOfficeInfoClient.getCustByHashNo(customerId).getPropertyLOVs()
            .flatMap(property -> property.getValues().values().stream())
            .collect(Collectors.toSet());
}

错误栈:

java.lang.UnsupportedOperationException
    at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:71)
    at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.addAll(ImmutableCollections.java:76)
    at service.impl.UserManagementServiceImpl.lambda$validateNewLogin$3(UserManagementServiceImpl.java:69)

将代码改为以下形式后恢复正常:

var allNumbersSet = new HashSet<>(customerInfoService.getCustomerPhoneNumbers(bankCustomerId));

原代码问题

原代码直接使用getCustomerPhoneNumbers返回的Set实例执行修改操作(addAll),但该实例实际是不可变集合,不支持任何修改类操作。

异常具体原因

虽然Collectors.toSet()默认返回可变的HashSet,但结合Hazelcast缓存场景:当方法返回的集合被存入Hazelcast缓存时,缓存被配置为将集合转换为JDK 11提供的ImmutableCollections系列不可变集合(比如ImmutableSet)。后续从缓存获取该集合时,拿到的是不可变实现,调用addAll这类修改方法就会触发UnsupportedOperationException——错误栈中的ImmutableCollections.uoe也验证了这一点,uoe正是"Unsupported Operation Exception"的缩写。

解决方案

方案1:包装为可变集合

将返回的不可变集合传入可变集合的构造方法,创建一个可修改的副本:

var allNumbersSet = new HashSet<>(customerInfoService.getCustomerPhoneNumbers(bankCustomerId));

方案2:流式合并集合

直接通过Stream API合并两个集合,避免对原集合的修改操作:

Set<String> allNumbersSet = Stream.concat(
    // 初始手机号集合流
    customerInfoService.getCustomerPhoneNumbers(bankCustomerId).stream(),
    // 额外手机号集合流
    additionalInformation
        .map(info -> info.get(BANK_PE_CUSTOMER_ID_KEY))
        .filter(StringUtils::isNotEmpty)
        .map(customerInfoService::getCustomerPhoneNumbers)
        .flatMap(Set::stream)
).collect(Collectors.toCollection(HashSet::new)); // 明确指定可变集合实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:20:16