java stream分组,并在一次迭代中找到前10名

java stream分组,并在一次迭代中找到前10名,java,java-8,java-stream,Java,Java 8,Java Stream,它与此不同,因为我想在一次迭代中解决这个问题 假设我有以下实体: public static class Hospital { private AREA area; private int patients; public Hospital(AREA area, int patients) { this.area = area; this.patients = patients; } public AREA getAre

它与此不同,因为我想在一次迭代中解决这个问题

假设我有以下实体:

public static class Hospital {
    private AREA area;
    private int patients;

    public Hospital(AREA area, int patients) {
        this.area = area;
        this.patients = patients;
    }

    public AREA getArea() {
        return area;
    }

    public void setArea(AREA area) {
        this.area = area;
    }

    public int getPatients() {
        return patients;
    }

    public void setPatients(int patients) {
        this.patients = patients;
    }
}

public enum AREA {
    AREA1,
    AREA2,
    AREA3
}
现在,我列出了一份医院名单,我想找出病人最多的地区,以下是我迄今为止所做的工作:

public static void main(String[] args) {
    List<Hospital> list = Arrays.asList(
            new Hospital(AREA.AREA1, 20),
            new Hospital(AREA.AREA2, 10),
            new Hospital(AREA.AREA1, 10),
            new Hospital(AREA.AREA3, 40),
            new Hospital(AREA.AREA2, 10));
    Map<AREA, Integer> map = findTopTen(list);
    for (AREA area : map.keySet())
        System.out.println(area);

}

public static Map<AREA, Integer> findTopTen(Iterable<Hospital> iterable) {
    Map<AREA, Integer> map = StreamSupport.stream(iterable.spliterator(), false)
            .collect(Collectors.groupingBy(Hospital::getArea,
                    Collectors.summingInt(Hospital::getPatients)));
    for (Map.Entry<AREA, Integer> area : map.entrySet())
        System.out.println(area.getKey() + "...." + area.getValue());
    return map.entrySet().stream()
            .sorted((e1, e2) -> e2.getValue() - e1.getValue())
            .collect(Collectors.toMap(Map.Entry::getKey,
                    Map.Entry::getValue, (o, o2) -> o,
                    LinkedHashMap::new));

}
publicstaticvoidmain(字符串[]args){
List=Arrays.asList(
新医院(1区、20区),
新医院(2区、10区),
新医院(1区、10区),
新医院(3区、40区),
新医院(2区、10区);
Map Map=findTopTen(列表);
用于(区域:map.keySet())
系统输出打印LN(面积);
}
公共静态映射findTopTen(Iterable Iterable){
Map Map=StreamSupport.stream(iterable.spliterator(),false)
.collect(收集器).groupingBy(医院::getArea,
汇总(医院::获取患者));
对于(Map.Entry区域:Map.entrySet())
System.out.println(area.getKey()+“…”+area.getValue());
返回map.entrySet().stream()
.sorted((e1,e2)->e2.getValue()-e1.getValue())
.collect(Collectors.toMap(Map.Entry::getKey、,
Map.Entry::getValue,(o,o2)->o,
LinkedHashMap::new));
}
很明显,我已经迭代了两次,以找到其中大多数患者的前十个区域(一次用于按区域对医院进行分组并计算该组的总和,另一次用于查找前十个区域)

现在我想知道的是:

1)有没有更好的方法在一个流中解决这个问题,从而在一次迭代中解决这个问题?


2)在一次迭代中执行此操作是否有任何性能优势,解决此类问题的最佳实践是什么?(在我看来,一方面,当我调用
collect
这是一个终端操作时,它第一次迭代我的iterable并将中间结果保存在另一个对象中,在我的代码中,我将该对象命名为iterationOneResult,因此使用一个流并调用collect一次将忽略中间结果,这是u另一方面,在java中使用sing stream在一次迭代中解决此问题将复杂性从O(2n)降低到O(n))

使用stream在一次迭代中很难做到这一点,但使用一个流链可以更简洁

Map<AREA, Integer> map = list.stream()
        .collect(Collectors.groupingBy(Hospital::getArea, Collectors.summingInt(Hospital::getPatients)))
        .entrySet().stream()
        .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
        .limit(10)
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

.entrySet().stream()之后的rigth

谢谢你的回答,顺便说一句,考虑到性能,我想在一次迭代中完成,我想在这里讨论这样做是否对性能有好处,在你的方法中,收集时间意味着两次独立的迭代。@Ruslan如果这纯粹是一个基于复杂性的问题,那么你可能需要创建另一个线程请注意,另一方面,在谈论绩效时,不要忘记创建基准。对于我还想建议的内容,请参考第(1)部分是在链接问题中的行上尝试解决方案。在java Stream API中,当您调用collect时,上一个迭代结束,上一个流关闭。您前面提到的答案和另一个问题链接都通过调用collect两次在两次迭代中解决了此问题。我想准确地解决此问题一次迭代。请仔细阅读我的问题,它与您提到的其他问题不同。我想在一次迭代@Naman中解决这个问题
.peek(e -> System.out.println(e.getKey() + " " + e.getValue()))