Java 8:使用流检查两个列表中的公共元素

时间:2018-10-24 08:56:38

标签: java optimization java-8 java-stream

根据用户名,我正在寻找一条语句来检查两个用户列表中是否有匹配项。

List<User> a;
List<User> b;
for (User user : a) {
    for (User newUser : b) {
        if (user.getName().equals(newUser.getName())) {
        }
    }
}

如何用Java 8编写此代码?像这样的东西:

List<User> intersect = a.stream()
                    .filter(User::getName)
                    .collect(Collectors.toList());

3 个答案:

答案 0 :(得分:3)

如果使用hashCodeequals正确定义了User(否则,您可以尝试使用TreeSet而不是HashSet),请执行设置操作:

Set<User> common = new HashSet<>(a);
common.retainAll(b);

如果User.getName不用于相等:

Set<User> common = new TreeSet<>(Comparator.comparing(User::getName));
common.addAll(a);
common.retainAll(b);

列表(也作为流)上的两个嵌套的for循环的复杂度为O(N²), 而这是O(N.log N)。

答案 1 :(得分:1)

您可以执行以下操作:

List<User> intersect = a.stream()
                     .filter(b::contains)
                     .collect(Collectors.toList());

您需要覆盖equals中的hashCodeUser方法。 为了进行优化,您可以先将b转换为HashSet

答案 2 :(得分:0)

使用Stream.anyMatch(在break中将if)做到这一点的一种方法可能是:

a.stream().filter(user -> b.stream().anyMatch(newUser -> user.getName().equals(newUser.getName())))
          .map(User::getName)
          .forEach(System.out::println); // logic inside 'if' here (print for e.g.)

如果您想对所有此类匹配重复循环(if逻辑):

a.forEach(user -> b.stream()
                   .filter(newUser -> user.getName().equals(newUser.getName()))
                   .map(newUser -> user.getName())
                   .forEach(System.out::println));