我面临一个小问题,要将我的两个for重写为Java 8流。
// This is a method parameter
Map<String, Collection<String>> preSelectedValues;
List<PersonModel> parameters = parameterSearchService.getParameterNames();
for(Iterator<Map.Entry<String, Collection<String>>> it = preSelectedValues.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Collection<String>> entry = it.next();
for(int i = 0; i < parameters.size(); i++) {
if (entry.getKey().startsWith(parameters.get(i).getName())) {
it.remove();
}
}
}
我尝试了以下流以具有与以前相同的行为:
Map<String, Collection<String>> filteredParameters = preSelectedValues.keySet().stream()
.filter(x -> isParameterValid(x, parameters))
.collect(Collectors.toMap(k -> k, v -> preSelectedValues.get(v)));
isParameterValid
方法:private boolean isParameterValid(String parameterId, List<PersonModel> preSelectedValues) {
return preSelectedValues.stream()
.anyMatch(v -> !v.getName().startsWith(parameterId));
}
基本上,我想做的是过滤以“parameterId”开头的“preSelectedValues”映射。但是以某种方式,当我使用流时,它要么过滤所有内容,要么什么都不过滤。
最佳答案
您的isParameterValid
方法与原始循环的逻辑不同,因为:
startsWith
。 anyMatch
调用!v.getName().startsWith(parameterId)
仅告诉您List<PersonModel>
的至少一个元素是否不是以parameterId
开头。将条目保留在Map
中的原始条件是所有 List<PersonModel>
的元素都不以parameterId
开头(或者实际上,相反-parameterId
并不以List<PersonModel>
元素的任何名称开头)。 因此,我否定了该方法以返回从
Map
中删除条目的条件:private boolean isParameterInvalid(String parameterId, List<PersonModel> preSelectedValues) {
return preSelectedValues.stream()
.anyMatch(v -> parameterId.startsWith(v.getName()));
}
然后,流管道可以如下所示:
Map<String, Collection<String>> filteredParameters = preSelectedValues.entrySet().stream()
.filter(x -> !isParameterInvalid(x.getKey(), parameters))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
顺便说一句,由于您的原始循环会变异原始的
Map
,因此您可以使用removeIf
实现相同的目的。