调用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
相关产品推荐
相关产品推荐

