当前位置: 首页 > 知识库问答 >
问题:

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

卫烨
2023-03-14

它推迟了这个如何在使用Java流分组后应用排序和限制,因为我想在一次迭代中解决这个问题

假设我有以下实体:

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

}

显然,我已经迭代了两次,以找到其中包含大多数患者的前十个区域(一次用于按区域对医院进行分组并计算该组的总和,一次用于查找前十个区域)。

现在我想知道的是:

1) 有没有更好的方法可以在一个流和一次迭代中解决这个问题?

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

共有1个答案

梁鸣
2023-03-14

这很难在使用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));

此外,如果要打印中间结果(仅用于调试目的),可以插入

.peek(e -> System.out.println(e.getKey() + " " + e.getValue()))

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

 类似资料:
  • 问题内容: 我正在尝试使用Angular创建Metro Tile类型的网格,以实现这一目标,我希望每个瓷砖都具有不同的颜色。因此,我的行动计划是创建一个函数,该函数将在循环内随机选择一种颜色(使用)。这是我到目前为止所拥有的… 如您所见,我正在使用名为RandomColourClass的函数设置类名称,这是JS位 这一切工作正常,并且图块具有不同的颜色,但我一直收到以下错误 错误:达到10个$ d

  • 问题内容: 我有一个’ ‘ 形式的数组,它代表一个小网格的坐标。每个坐标已分配了自己的值。例如…… 我有两个问题。首先,我如何遍历所有存储的值。其次,我希望能够输入一个值并返回其在网格中的特定坐标。解决这个问题的最佳方法是什么? 感谢您的任何帮助! 问题答案: 您可以使用for循环或增强的for循环进行迭代: 要么 第一个版本将是“查找坐标”问题的最简单解决方案-只需检查内部循环中的值是否正确即可

  • 问题内容: 我是Angular的新手,并且遇到了与IE相关的问题。 这是我得到的IE错误。 在IE 8和IE 9之外的任何其他浏览器中都不会发生这种情况。 我有一只手表在看一个包含位置过滤器的内容过滤对象。 我对此的疑问是,为什么它不会在除IE之外的任何其他浏览器上发生,并且我应该怎么做才能消除它。提前致谢。 问题答案: 我有相同的问题,看起来却一样。Chrome \ FF工作正常,但IE失败。我

  • 迭代器并不是Ruby发明的.它广泛地运用于各种面向对象语言.在Lisp中也有,只是不这么叫罢了.尽管如此,迭代器的概念并不为许多人熟悉,因此我们将在此做较为详细的介绍. 你知道,动词 iterate 的意思是做同一件事许多遍,因此,iterator就是用来将同一件事做许多次的东西. 当我们写代码时,我们需要各种环境下的循环.在C里,我们用for或者while.比如, char *str; for

  • 问题内容: 达到10个$ digest()迭代。流产! 有很多支持文本,例如“在最近5个迭代中触发了Watchers:”等,但是其中很多文本是来自各种功能的Javascript代码。有诊断此问题的经验法则吗?是可以始终缓解的问题,还是应用程序足够复杂,因此应将其视为警告? 问题答案: 正如Ven所说,您或者在每个循环中返回不同(不相同)的对象,或者您将数据更改了太多次。 确定您的应用程序的哪个部分

  • 如果我试图在java中查找遍历foreach循环的次数,还有比这更好的方法吗? 我知道我可以只使用一个普通的for循环并拥有一个迭代器I,但我只是想知道是否有一种更优雅的方法来使用foreach.tanks in prevair:) 编辑:正如Jon Skeet指出的,上面的代码将新的按钮实例分配给迭代变量。哎呀。基于其他评论,我相信最实用的使用是一个正常循环。这是我要用的版本。谢谢大家的帮助!