Java 8组由sum条件组成

时间:2017-11-02 18:25:33

标签: group-by java-8 java-stream

我有一名对象主任

public class Officer {

    private String name;
    private int totalDaysInOffice;

    public Officer(String name, int totalDaysInOffice) {
        this.name = name;
        this.totalDaysInOffice = totalDaysInOffice;
    }

    @Override
    public String toString() {
        return "Officer{" +
                "name='" + name + '\'' +
                ", totalDaysInOffice=" + totalDaysInOffice +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getTotalDaysInOffice() {
        return totalDaysInOffice;
    }

    public void setTotalDaysInOffice(int totalDaysInOffice) {
        this.totalDaysInOffice = totalDaysInOffice;
    }
}

这里每位军官都在办公室呆了几天(只是组成变量)。

我想要做的是在一个单独的清单中将天数总和10000划分给警员

根据以下示例,我希望列出

one list with John , Matthew , and Robert since they sum to more 10K 
One list with Patrick as he has 10K 
Dave would be in separate list.

我尝试过分组,但不确定如何添加此条件。

public class OffierExample {

    public static void main(String[] args) {

        List<Officer> officerList = new ArrayList<>();

        officerList.add(new Officer("John",5000));
        officerList.add(new Officer("Matthew",3000));
        officerList.add(new Officer("Robert",2000));
        officerList.add(new Officer("Dave",2000));
        officerList.add(new Officer("Patrick",10000));

        Map<Officer, Integer> collect = officerList.stream().collect(Collectors.groupingBy(o -> o, Collectors.summingInt(Officer::getTotalDaysInOffice)));
        System.out.println(collect);
    }
}

无论如何,它可以在Java 8中完成

**

***** UPDATE *****

**

我已经实现了使用传统循环,但我希望尽可能使用Java 8组

public class OffierExample {

    public static void main(String[] args) {

        List<Officer> officerList = new ArrayList<>();

        officerList.add(new Officer("John", 5000));
        officerList.add(new Officer("Matthew", 3000));
        officerList.add(new Officer("Robert", 2000));
        officerList.add(new Officer("Dave", 2000));
        officerList.add(new Officer("Patrick", 10000));

        officerList.add(new Officer("YYYY", 600));
        officerList.add(new Officer("XXXX", 600));

        //keep totalDaysInOfficeSum
        int totalDaysInOfficeSum = 0;

        //the final list
        List<List<Officer>> off = Lists.newArrayList();

        //the working list
        List<Officer> tempOffList = Lists.newArrayList();

        for (Officer officer : officerList) {

            //get sum
            totalDaysInOfficeSum = totalDaysInOfficeSum + officer.getTotalDaysInOffice();

            //if sum is more than 10K or equal
            if (totalDaysInOfficeSum >= 10000) {

                //add it in temp list
                tempOffList.add(officer);

                //add in master list
                off.add(tempOffList);

                //reset temp list
                tempOffList = new ArrayList<>();

                //reset sum
                totalDaysInOfficeSum = 0;
                continue;

            }

            //add in temp list
            tempOffList.add(officer);


        }

        //any left over
        if (!tempOffList.isEmpty()) {
            off.add(tempOffList);
        }

        //printint out
        System.out.println("Officers list =" + off.size());

        off.forEach(o -> {

            System.out.println("List size:" + o.size());
            o.forEach(oo -> {
                System.out.println(oo.getName() + "::" + oo.getTotalDaysInOffice());
            });
            System.out.println("====================");
        });
    }
}

输出

Officers list =3
List size:3
John::5000
Matthew::3000
Robert::2000
====================
List size:2
Dave::2000
Patrick::10000
====================
List size:2
YYYY::600
XXXX::600
====================

2 个答案:

答案 0 :(得分:2)

这样的事情:

List<List<Officer>> result = officerList.stream().collect(Collector.of(
            () -> new ArrayList<List<Officer>>(),
            (list, entry) -> {
                if (list.size() == 0) {
                    List<Officer> inner = new ArrayList<>();
                    inner.add(entry);
                    list.add(inner);
                } else {
                    List<Officer> last = list.get(list.size() - 1);
                    int sum = last.stream().mapToInt(Officer::getTotalDaysInOffice).sum();
                    if (sum < 10_000) {
                        last.add(entry);
                    } else {
                        List<Officer> inner = new ArrayList<>();
                        inner.add(entry);
                        list.add(inner);
                    }
                }
            },
            (left, right) -> {
                throw new IllegalArgumentException("Not for parallel");
            }));

答案 1 :(得分:0)

以下是my library的解决方案:

MutableInt sum = MutableInt.of(0);
List<List<Officer>> off = Stream.of(officerList)
        .splitToList(officer -> sum.getAndSet(sum.value() < 10000 ? sum.value() + officer.getTotalDaysInOffice() : 0) < 10000)
        .toList();

或者:

List<List<Officer>> off = Seq.of(officerList)
        .split(officer -> sum.getAndSet(sum.value() < 10000 ? sum.value() + officer.getTotalDaysInOffice() : 0) < 10000);
相关问题