2

I'm looking for a statment to check if there is any match in two lists of Users, according to Username.

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

How can I write this in java 8? Somthing like this:

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

3 Answers 3

3

When User is correctly defined with a hashCode and equals (otherwise you might try TreeSet instead of HashSet), do set-operations:

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

If User.getName is not used for equality:

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

Two nested for loops on lists (also as streams) would have complexity O(N²), whereas this is O(N.log N).

Sign up to request clarification or add additional context in comments.

6 Comments

retainAll returns boolean
Would this automatically call getName?
@AhmadAl-Khazraji you hit the weak spot; thanks. Added a comparator. If two different users can have the same name, it would make more sense to return a Set<String> of names. Then a Stream solution with a mapping would be in order.
@AhmadAl-Khazraji new TreeSet<>(a, Comparator.comparing(User::getName)) should keep only users with no duplicate names.
@AhmadAl-Khazraji my error, one needs 2 calls. Corrected, Sorry, today I should not have played on StackOverflow.
|
2

You can do something like below:

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

You need to override equals and hashCode methods in User. For optimization, you can convert b to HashSet first.

1 Comment

I can't overreide any method in the class User!
1

One way to do that using Stream.anyMatch(this would break within if) could be :

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 you want to repeat the loop(if logic) for all such matches :

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

1 Comment

You can save one user.getName() call per user, by simply doing the map(User::getName) first.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.