java stream按属性排序/过滤列表

时间:2016-10-24 16:44:38

标签: java sorting collections lambda

我有一些逻辑可以根据非活动用户创建通知。我收到了具有以下属性的用户列表。我想要做的只是在部门有非活动用户时触发我的创建通知方法。因此,根据下面的列表,基本上会创建一个通知,说明在部门1中有一个非活动用户,另一个部门有另一个通知。希望这有意义

users:
{name: John, active: f, deptId: 1}
{name: Jane, active: f, deptId: 1}
{name: Mike, active: t, deptId: 1}
{name: Joe, active: f, deptId: 2}
{name: Jim, active: t, deptId: 2}

我当前的代码基本上会得到这个列表,然后检查每个用户的活动标志并为每个用户创建一个通知 - 但我需要重构它。

List<User> users = userRepository.findAll();
for(User u : users){
    if(u != null && u.getActive == false){
        ....create Notification method

按部门对这些进行分组然后仅检查每个组的活动标志是否为false以及为每个不活动的用户创建1个通知而不是通知的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

也许您会发现以下代码段有用:

public Map<String, List<User>> getInactiveUsersByDepartment(List<User> allUsers) {
    return allUsers.stream().filter(user -> user != null).filter(user -> !user.getActive()).collect(Collectors.groupingBy(User::getDepartment));
}

答案 1 :(得分:0)

首先过滤掉null和活跃用户,因为您只会对那些不活跃的用户感兴趣。然后,按部门ID对结果进行分组。使用生成的映射迭代密钥集,即具有非活动用户的部门:

users.stream().filter(Objects::nonNull)
        .filter(((Predicate<User>) User::isActive).negate())
        .collect(Collectors.groupingBy(User::getDeptId))
        .keySet().forEach(Notifier::notifyDepartment);

请注意,您也可以使用lambda表达式而不是方法引用(例如user -> !user.isActive()),这只是一种风格问题。

您可以使用此MCVE来实现实施,它只是打印出受影响的部门:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class ReportInactiveUsers {

    public static void main(String[] args) {
        User u1 = new User("John", false, 1);
        User u2 = new User("Jane", false, 1);
        User u3 = new User("Mike", true, 1);
        User u4 = new User("Joe", false, 2);
        User u5 = new User("Jim", true, 2);
        User u6 = null;
        List<User> users = Arrays.asList(u1, u2, u3, u4, u5, u6);

        users.stream().filter(Objects::nonNull)
                .filter(((Predicate<User>) User::isActive).negate())
                .collect(Collectors.groupingBy(User::getDeptId))
                .keySet().forEach(System.out::println);
    }

    public static class User {
        private String name;
        private boolean active;
        private int deptId;

        public User(String name, boolean active, int deptId) {
            this.name = name;
            this.active = active;
            this.deptId = deptId;
        }

        public String getName() {
            return name;
        }

        public boolean isActive() {
            return active;
        }

        public int getDeptId() {
            return deptId;
        }
    }

}