我面临一个小问题,要将我的两个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实现相同的目的。

    09-25 20:17