52

I have two list and i want filter thoose elements which are both list contains. And i want to do this with lambda expression.

Users getName and Clients getUserName both are return with String.

Here is my sample code:

List<Client> clients = new ArrayList<>();
List<User> users = new ArrayList<>();
List<Client> results = new ArrayList<>();

for (Client user : users) {
    for(Client client: clients){
        if(user.getName().equals(client.getUserName())){
            result.add(client);
        }
    }
}
1
  • 3
    Your code won't compile; a User is not a Client, unless User inherits Client. Commented May 3, 2015 at 9:45

4 Answers 4

103
Predicate<Client> hasSameNameAsOneUser = 
    c -> users.stream().anyMatch(u -> u.getName().equals(c.getName()));

return clients.stream()
              .filter(hasSameNameAsOneUser)
              .collect(Collectors.toList());

But this is quite inefficient, because it's O(m * n). You'd better create a Set of acceptable names:

Set<String> acceptableNames = 
    users.stream()
         .map(User::getName)
         .collect(Collectors.toSet());

return clients.stream()
              .filter(c -> acceptableNames.contains(c.getName()))
              .collect(Collectors.toList());

Also note that it's not strictly equivalent to the code you have (if it compiled), which adds the same client twice to the list if several users have the same name as the client.

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

3 Comments

I'm curious how the second implementation is more efficient? It looks likei it is still O(m * n) to me. When we do acceptableNames.contains(...) we are traversing that set. Is the idea that the Set will weed out duplicates so it is a slightly better O(m * n)?
No. Calling contains() on a List does traverse the list. But calling contains on a HashSet just computes the hashCode and traverses the bucket corresponding to that hashCode, which typically contains 0 or 1 element. A HashSet contains lookup is O(1).
Ah, I understand. Calling .contains() on a list would be O(n), but O(1) on HashSet. Thanks for the clarification!
8

Look this:

List<Client> result = clients
    .stream()
    .filter(c -> 
        (users.stream().map(User::getName).collect(Collectors.toList())).contains(c.getName()))
        .collect(Collectors.toList());

1 Comment

users.stream().map(User::getName).collect(Collectors.toList()) It is more efficient if you use Collectors.toSet() for users to distinct user.name
6

I would like share an example to understand the usage of stream().filter

Code Snippet: Sample program to identify even number.

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public void fetchEvenNumber(){
        List<Integer> numberList = new ArrayList<>();
        numberList.add(10);
        numberList.add(11);
        numberList.add(12);
        numberList.add(13);
        numberList.add(14);
        numberList.add(15);

        List<Integer> evenNumberListObj = numberList.stream().filter(i -> i%2 == 0).collect(Collectors.toList());
        System.out.println(evenNumberListObj);
}

Output will be : [10, 12, 14]

List evenNumberListObj = numberList.stream().filter(i -> i%2 == 0).collect(Collectors.toList());

numberList: it is an ArrayList object contains list of numbers.

java.util.Collection.stream() : stream() will get the stream of collection, which will return the Stream of Integer.

filter: Returns a stream that match the given predicate. i.e based on given condition (i -> i%2 != 0) returns the matching stream.

collect: whatever the stream of Integer filter based in the filter condition, those integer will be put in a list.

Comments

2

Something like:

clients.stream.filter(c->{
   users.stream.filter(u->u.getName().equals(c.getName()).count()>0
}).collect(Collectors.toList());

This is however not an awfully efficient way to do it. Unless the collections are very small, you will be better of building a set of user names and using that in the condition.

2 Comments

We are not comparing objects by their equals method here. Please reread the question.
I see you corrected approach in your answer but there are still minor problems with it. Please don't post answer if you didn't test it first. There is no shame in deleting it to avoid farther downvoting and confusion, correcting it in the shadows and undeleting it when it is correct.

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.