首页 > 解决方案 > 将两个 for 重构为 java 8 流

问题描述

我面临一个小问题,将我的两个 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”映射。但不知何故,当我使用流时,它要么过滤一切,要么什么都不过滤。

标签: javajava-8java-stream

解决方案


Your isParameterValid method doesn't have the same logic as the original loops, since:

  1. You switched the instance and argument in the call to startsWith.
  2. Calling anyMatch with a !v.getName().startsWith(parameterId) only tells you whether at least one element of the List<PersonModel> doesn't start with parameterId. Your original condition for keeping the entry in the Map was that all the elements of List<PersonModel> don't start with parameterId (or actually, the other way around - parameterId doesn't start with any of the names of elements of List<PersonModel>).

Therefore I negated the method to return the condition for removing an entry from the Map:

private boolean isParameterInvalid(String parameterId, List<PersonModel> preSelectedValues) {
     return preSelectedValues.stream()
            .anyMatch(v -> parameterId.startsWith(v.getName()));
}

And then the stream pipeline can look like this:

Map<String, Collection<String>> filteredParameters = preSelectedValues.entrySet().stream()
    .filter(x -> !isParameterInvalid(x.getKey(), parameters))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

BTW, since your original loops mutate the original Map, you can achieve the same with removeIf.


推荐阅读