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

使用Java 8流API进行计数和排序

朱宏爽
2023-03-14

我想知道这怎么会被COUNT然后ASC订购。

Stream<String> fruits = Stream.of("apple", "orange", "ananas");

Map<String, Long> letters =
   fruits.map(w -> w.split(""))
              .flatMap(Arrays::stream)
              .collect(groupingBy(identity(), counting()));

输出:

{p=2, a=5, r=1, s=1, e=2, g=1, l=1, n=3, o=1}`

所需输出:

{a=5, n=3, e=2, p=2, g=1, l=1, r=1, s=1, o=1}

共有2个答案

孟浩慨
2023-03-14

您不能按其值对映射进行排序。我认为您可以实现的最佳效果是将排序的条目存储到LinkedHashMap中,这样当您迭代其他它时,您将获得预期的结果(因为您将按所需的排序顺序添加映射)。

为此,您需要一个操作分组,以了解如何构建映射字母-

然后,您必须再次迭代条目集,并对流进行排序,以便条目首先按其值排序,然后按键的自然顺序排序。因此,比较器将如下所示:

//need to provide explicit type parameters due to limited type inference at the moment
Comparator<Map.Entry<String, Long>> cmp = 
    Map.Entry.<String, Long>comparingByValue(reverseOrder()).thenComparing(Map.Entry.comparingByKey());

将所有部件组合在一起,可以得到:

Map<String, Long> letters =
    fruits.flatMap(w -> Arrays.stream(w.split("")))
          .collect(groupingBy(identity(), counting()))
          .entrySet()
          .stream()
          .sorted(Map.Entry.<String, Long>comparingByValue(reverseOrder()).thenComparing(Map.Entry.comparingByKey()))
          .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> {throw new IllegalStateException();}, LinkedHashMap::new));

产生:

{a=5, n=3, e=2, p=2, g=1, l=1, o=1, r=1, s=1}
上官鸿祯
2023-03-14

不可避免地要分两个映射步骤进行,因为首先需要计数,然后才能根据计数进行排序:

Map<String, Long> letters = fruits
    .flatMap(Pattern.compile("")::splitAsStream)
    .collect(groupingBy(identity(), counting()))
    .entrySet().stream().sorted(Map.Entry.comparingByValue(reverseOrder()))
    .collect(LinkedHashMap::new, (m,e) -> m.put(e.getKey(), e.getValue()), Map::putAll);

如果假设只有ASCII小写字母(或任何其他小型固定大小的字符集),可以尝试一种可能更有效的替代方法。它将字符和计数作为基本值进行处理,存储在固定大小的数组中。仅为最终排序和映射生成生成对象:

long[] histogram=fruits.flatMapToInt(String::chars)
    .filter(c -> c>='a' && c<='z')// just to be sure, remove if you prefer exceptions
    .collect(()->new long[26],(a,c)->a[c-'a']++, (a,b)->Arrays.setAll(a, ix->a[ix]+b[ix]));
Map<String, Long> letters=IntStream.range(0, 26).filter(i->histogram[i]!=0)
    .boxed().sorted(comparingLong(i -> -histogram[i]))
    .collect(LinkedHashMap::new, (m,i)->m.put(""+(char)(i+'a'),histogram[i]), Map::putAll);
 类似资料:
  • 问题内容: 我的清单包含大小等的集合。我尝试这样做,但似乎不起作用。 我想要的最终结果是。 我可以尝试添加在所有的元素和那种出来再做出新的的。但是,有某种班轮吗? 更新: 这可行,但是可以简化吗? 问题答案: @Eugene的回答很甜蜜,因为番石榴很甜。但是,如果您碰巧在类路径中没有番石榴,这是另一种方式: 首先,我将所有集合映射到一个流中,然后对所有元素进行排序,最后,将整个排序后的流收集到集合

  • 我正在使用java lambda对列表进行排序。 我怎样才能反向排序呢?

  • 我正在努力得到正确的语法下面。我尝试过不同的工会,但都没有成功。 我需要将这三个总数相加为“totcount”。数据表非常大,希望找到一种比第4个子查询更好的方法来获取totcount。

  • 我有这个列表,我想按保留顺序订购,但我没有在自动完成辅助中找到任何函数 我也尝试过: 但是我有编译错误:

  • 我正在使用我有一个类,如下所示: 现在我想做的是: 筛选出senderId无效的记录(使用映射) 下面是我的代码: 这给我带来了一个错误: 错误:(105,90)java:找不到适用于groupingBy(共享[…]的方法gMode,java。util。作用函数)方法java。util。流动收藏家。groupingBy(java.util.function.function)不适用(无法推断类型变

  • 我有一个这样的方法: 此方法需要以如下字符串形式返回3个最昂贵项目的产品ID:“item1,item2,item3”。我应该只能使用溪流,我被困在这里了。我应该能够按值对项目进行排序,然后获得产品ID,但我似乎无法使其正常工作。 编辑: 产品ID位于入口类中