3

I want to use Java 8 stream filter collections but i found all example is one collections , Java 6 is :

public class User {
public Long id;
public String name;

public User(Long id, String name) {
    this.id = id;
    this.name = name;
}

   List<User> usersA = new ArrayList<>();

    usersA.add(new User(1l,"A"));
    usersA.add(new User(2l,"B"));
    usersA.add(new User(3l,"C"));

    List<User> usersB = new ArrayList<>();
    usersB.add(new User(33l,"A"));
    usersB.add(new User(34l,"B"));
    usersB.add(new User(35l,"D"));
    usersB.add(new User(36l,"C"));

    List<User> tempUser = new ArrayList<>();
    tempUser.addAll(usersB);

    for (User user : usersA) {
        for (User user1 : tempUser) {
            System.out.println(user1.getName().equalsIgnoreCase(user.getName()));
            if (user1.getName().equalsIgnoreCase(user.getName())){
                System.out.println("remove:"+user1.getName());
                tempUser.remove(user1);
                break;
            }
        }

    }

    System.out.println("last:"+tempUser);

And Java 8 I want to use stream api not use foreach ,can u take a example for me ? thanks

4 Answers 4

7

So, if I understand correctly, you want to create a new list containing all the users of usersB, except those that have the same name as any of the users in usersA, right?

First of all, I would change the strategy: instead of adding all the users, then removing some, I would only add the users that belong to the list in the first place.

And in Java 8, that can be done with

List<User> result = 
    usersB.stream()
          .filter(u -> !userNameIn(u, usersA))
          .collect(Collectors.toList());

with userNameIn defined as

private boolean userNameIn(User u, List<User> users) {
    return users.stream().anyMatch(user -> user.getName().equalsIgnoreCase(u.getName()));
}

That won't be very efficient if usersA contains a large number of users. A more efficient solution would be to store all the lowercase names of usersA in a HashSet, and replace the method with

List<User> result = 
    usersB.stream()
          .filter(u -> !lowercaseNames.contains(u.getName().toLowerCase()))
          .collect(Collectors.toList());
Sign up to request clarification or add additional context in comments.

Comments

3

You should avoid repeated lookups using linear search as you do with your nested loops. This can become a performance disaster when the collections grow.

First, collect the names of the first collection into a Set supporting the desired lookup:

Set<String> namesInA=usersA.stream().map(User::getName)
    .collect(Collectors.toCollection(() -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER)));

Then you can perform the operation in either of two fashions:

  1. In-place in a collection:

    List<User> tempUser = new ArrayList<>(usersB);
    tempUser.removeIf(u -> namesInA.contains(u.getName()));
    
  2. Using the stream API to collect matching elements into a new collection:

    List<User> tempUser = usersB.stream()
        .filter(u->!namesInA.contains(u.getName()))
        .collect(Collectors.toList());
    

Comments

0

I would do something like that:

public static class User {
    public Long id;
    public String name;

    public User(Long id, String name) {
        this.id = id;
        this.name = name;
    }
}
public static void main(String[] args){


    List<User> usersA = new ArrayList<>();

    usersA.add(new User(1l,"A"));
    usersA.add(new User(2l,"B"));
    usersA.add(new User(3l,"C"));

    List<User> usersB = new ArrayList<>();
    usersB.add(new User(33l,"A"));
    usersB.add(new User(34l,"B"));
    usersB.add(new User(35l,"D"));
    usersB.add(new User(36l,"C"));

    List<User> list = usersB.stream()
                    .filter(userb -> !usersA.stream().
                                    filter(usera -> usera.name.equalsIgnoreCase(userb.name)).findFirst().isPresent())
                    .collect(Collectors.toList());

}

Comments

-1

this can be done without any streams in java 8 and even better before in previous java versions.

http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html allows you to remove all items of one collection that are in the other collection. For the caller this is a one-liner then

userB.removeAll(userA)

this is correct when the objects of the collection implement equals

Comments

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.