简体   繁体   中英

How to use Map filter in list by Java 8 lambda

Map is Map<String, List<User>> and List is List<User> . I want to use

Map<String,List<User>> newMap = oldMap.stream()
.filter(u ->userList.stream()
.filter(ul ->ul.getName().equalsIgnoreCase(u.getKey()).count()>0))
.collect(Collectors.toMap(u.getKey, u.getVaule()));

can't change to new Map . Why?

Perhaps you intended to create a Stream of the entry Set of the input Map.

Map<String,List<User>> newMap =
    oldMap.entrySet().stream()
          .filter(u ->userList.stream().filter(ul ->ul.getName().equalsIgnoreCase(u.getKey())).count()>0)
          .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

This would create a Map that retains the entries of the original Map whose keys equal the name of at least one of the members of userList (ignoring case).

There are several problems with your code:

  • Map does not have a stream() : its entry set does, so you need to call entrySet() first.
  • There are a couple of misplaced parentheses
  • Collectors.toMap code is incorrect: you need to use the lambda u -> u.getKey() (or the method-reference Map.Entry::getKey ) and not just the expression u.getKey() . Also, you mispelled getValue() .

This would be a corrected code:

Map<String, List<User>> newMap = 
        oldMap.entrySet()
              .stream()
              .filter(u -> userList.stream()
                                   .filter(ul ->ul.getName().equalsIgnoreCase(u.getKey())).count() > 0             
              ).collect(Collectors.toMap(u -> u.getKey(), u -> u.getValue()));

But a couple of notes here:

  • You are filtering only to see if the count is greater than 0: instead you could just use anyMatch(predicate) . This is a short-cuiting terminal operation that returns true if the predicate is true for at least one of the elements in the Stream. This has also the advantage that this operation might not process all the elements in the Stream (when filtering does)
  • It is inefficient since you are traversing the userList every time you need to filter a Stream element. It would be better to use a Set which has O(1) lookup (so first you would convert your userList into a userSet , transforming the username in lower-case, and then you would search this set for a lower-case value username).

This would be a more performant code:

Set<String> userNameSet = userList.stream().map(u -> u.getName().toLowerCase(Locale.ROOT)).collect(toSet());
Map<String,List<User>> newMap = 
        oldMap.entrySet()
              .stream()
              .filter(u -> userNameSet.contains(u.getKey().toLowerCase(Locale.ROOT)))
              .collect(Collectors.toMap(u -> u.getKey(), u -> u.getValue()));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM