【问题标题】:Java 8 How to filter not different entity from two collections?Java 8 如何从两个集合中过滤不同的实体?
【发布时间】:2015-11-11 07:09:31
【问题描述】:

我想使用 Java 8 流过滤器集合,但我发现所有示例都是一个集合,Java 6 是:

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

Java 8 我想使用流 api 而不是 foreach,你能举个例子吗?谢谢

【问题讨论】:

    标签: java java-8 guava java-stream


    【解决方案1】:

    所以,如果我理解正确的话,您想创建一个包含usersB 的所有用户的新列表,除了那些与usersA 中的任何用户同名的用户,对吧?

    首先,我会改变策略:不是先添加所有用户,然后再删除一些用户,而是首先添加属于列表的用户。

    在 Java 8 中,可以使用

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

    userNameIn 定义为

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

    如果usersA 包含大量用户,那将不会很有效。一个更有效的解决方案是将usersA的所有小写名称存储在一个HashSet中,并将方法替换为

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

    【讨论】:

      【解决方案2】:

      您应该避免使用线性搜索重复查找,就像使用嵌套循环一样。当集合增长时,这可能会成为性能灾难。

      首先,将第一个集合的名称收集到支持所需查找的Set

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

      然后您可以通过以下两种方式之一执行操作:

      1. 在集合中就地:

        List<User> tempUser = new ArrayList<>(usersB);
        tempUser.removeIf(u -> namesInA.contains(u.getName()));
        
      2. 使用流 API 将匹配的元素收集到一个新集合中:

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

      【讨论】:

        【解决方案3】:

        我会这样做:

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

        【讨论】:

          【解决方案4】:

          这可以在 java 8 中没有任何流的情况下完成,在以前的 java 版本中甚至更好。

          http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html 允许您删除一个集合中在另一个集合中的所有项目。对于调用者,这是一个单行然后

          userB.removeAll(userA)

          当集合的对象实现equals时这是正确的

          【讨论】:

            猜你喜欢
            • 2016-05-09
            • 1970-01-01
            • 2014-11-27
            • 2019-07-10
            • 2013-03-23
            • 2016-12-27
            • 1970-01-01
            • 1970-01-01
            • 2014-03-05
            相关资源
            最近更新 更多