【发布时间】:2022-10-20 16:48:04
【问题描述】:
使用JDK 11.0.3。我有以下代码sn-p:
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))); // fails here
获取电话号码的地方只有Collectors.toSet():
@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));
它现在工作正常。
上面的代码使用有什么问题?你能解释一下为什么会出现这种情况吗?
这个方法调用被调用 Hazelcast 缓存包围 - 之前和之后。正如 cmets 所述,这可能是导致这种行为的原因:
缓存的值使用不可变集合表示,这是有道理的,因为它允许共享而不需要防御性副本
解决方案:
找到了如何重写这个逻辑并在不合并两组的情况下做这些事情的方法:
var numbersSet = customerInfoService.getCustomerPhoneNumbers(id); if (!numbersSet.contains(newLogin)) { var peNumbersSet = additionalInformation .map(info -> info.get(BANK_PE_CUSTOMER_ID_KEY)) .filter(StringUtils::isNotEmpty) .map(customerInfoService::getCustomerPhoneNumbers) .orElseGet(Collections::emptySet); if (!peNumbersSet.contains(newLogin)) { throw new ProcessException(ServerError.WRONG_LOGIN_PROVIDED.errorDTO()); } }重新思考一下这个逻辑:
var additionalInformation = Optional.ofNullable(user.getAdditionalInformation()); var phoneNumbers = new HashSet<String>(); additionalInformation .map(i -> i.get(BANK_CUSTOMER_ID_KEY)) .filter(StringUtils::isNotEmpty) .map(customerInfoService::getCustomerPhoneNumbers) .ifPresent(phoneNumbers::addAll); additionalInformation .map(i -> i.get(BANK_PE_CUSTOMER_ID_KEY)) .filter(StringUtils::isNotEmpty) .map(customerInfoService::getCustomerPhoneNumbers) .ifPresent(phoneNumbers::addAll); if (!phoneNumbers.contains(newLogin)) { throw new MetryusProcessException(AuthServerError.WRONG_LOGIN_PROVIDED.errorDTO()); }但是,了解
Collectors.toSet()在不同条件下的工作原理确实非常有用。
【问题讨论】:
-
@sp00m
import java.util.stream.Collectors; -
附带说明一下,无论如何改变参数都不是一个好主意,我会简单地实例化一个新的本地
HashSet,就像您尝试过的那样,即使您设法使getCustomerPhoneNumbers返回一个可变集。
标签: java exception set java-11 unsupportedoperation