【问题标题】:How do I create two different compliementary lists using same input如何使用相同的输入创建两个不同的互补列表
【发布时间】:2018-12-20 21:37:56
【问题描述】:

在我之前的问题 - How to filter the age while grouping in map with list 中,我能够使用 List<User> users 找到年龄组的名称。现在我正在尝试根据阈值从年龄中找到不同的用户组。我试过这个

List<User> userAboveThreshold = users.stream().filter(u -> u.getAge() > 21).collect(toList());
List<User> userBelowThreshold = users.stream().filter(u -> u.getAge() <= 21).collect(toList());

这一次我可以看到它的工作原理

userAboveThreshold.forEach(u -> System.out.println(u.getName() + " " + u.getAge()));
userBelowThreshold.forEach(u -> System.out.println(u.getName() + " " + u.getAge()));

但我必须再次访问 用户 列表才能找到免费列表。这不能简单点吗?

【问题讨论】:

    标签: java java-stream


    【解决方案1】:

    您正在关注partitioningBy 收集器:

    Map<Boolean, List<User>> result = 
                 users.stream().collect(partitioningBy(u -> u.getAge() > 21));
    

    然后按如下方式使用:

    List<User> userAboveThreshold = result.get(true);
    List<User> userBelowThreshold = result.get(false);
    

    【讨论】:

    • @Mani 好吧,您还应该知道,它在内部使用了一个只有两个键的专用映射,例如比 HashMap 更快的查找
    【解决方案2】:

    List.removeAll

    您可以使用removeAll获取免费名单。

    List<User> userBelowThreshold = new ArrayList<>(users); // initiated with 'users'
    userBelowThreshold.removeAll(userAboveThreshold);
    

    注意:这需要为 User 重写 equalshashCode 实现。


    Collectors.partitioningBy

    另一方面,如果您想进一步迭代完整的users 列表只需一次,您可以将Collectors.partitioningBy 用作:

    Map<Boolean, List<User>> userAgeMap = users.stream()
            .collect(Collectors.partitioningBy(user -> user.getAge() > 21, Collectors.toList()));
    List<User> userAboveThreshold = userAgeMap.get(Boolean.TRUE);
    List<User> userBelowThreshold = userAgeMap.get(Boolean.FALSE);
    

    【讨论】:

    • 对于那些担心在这里使用地图的成本的人,不用担心,Collectors.partitioningBy 返回一个 custom map class 直接存储 2 个分区(包含 truefalse 成员)内联。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多