Refactor two for's into java 8 streams

micu :

I'm facing a small problem to rewrite my two for's into java 8 streams.

// 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();
          }
     }
}

I've tried following streams to have the same behaviour as before:

Map<String, Collection<String>> filteredParameters = preSelectedValues.keySet().stream()
    .filter(x -> isParameterValid(x, parameters))
    .collect(Collectors.toMap(k -> k, v -> preSelectedValues.get(v)));

isParameterValid method:

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

Basically what I'm trying to do is filter the "preSelectedValues" map which starts with "parameterId". But somehow when I'm using streams either it filters everything or nothing.

Eran :

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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=90787&siteId=1