简体   繁体   English

如何通过Java 8 Lambda在列表中使用地图过滤器

[英]How to use Map filter in list by Java 8 lambda

Map is Map<String, List<User>> and List is List<User> . Map是Map<String, List<User>>并且List是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 . 无法更改为新的Map Why? 为什么?

Perhaps you intended to create a Stream of the entry Set of the input Map. 也许您打算创建输入Map的条目Set的Stream。

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). 这将创建一个Map ,保留原始Map的条目,这些条目的键等于userList成员中至少一个成员的名称(忽略大小写)。

There are several problems with your code: 您的代码有几个问题:

  • Map does not have a stream() : its entry set does, so you need to call entrySet() first. Map没有stream() :它的条目集有,所以您需要先调用entrySet()
  • 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() . Collectors.toMap代码不正确:您需要使用lambda u -> u.getKey() (或方法引用Map.Entry::getKey ),而不仅仅是表达式u.getKey() Also, you mispelled getValue() . 另外,您拼写了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) . 您仅在过滤以查看计数是否大于0:而是可以使用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. 这是一个简短的终端操作,如果谓词对于Stream中的至少一个元素为true ,则返回true This has also the advantage that this operation might not process all the elements in the Stream (when filtering does) 这还有一个优点,即此操作可能不会处理Stream中的所有元素(过滤时会处理)
  • It is inefficient since you are traversing the userList every time you need to filter a Stream element. 这是低效的,因为每次需要过滤Stream元素时都要遍历userList 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). 最好使用具有O(1)查找的Set (因此,首先将userList转换为userSet ,将用户名转换为小写,然后在该set中搜索小写值的用户名)。 。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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