J. *_*ter 4 java java-8 java-stream
我想知道如何由 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()));
Run Code Online (Sandbox Code Playgroud)
输出:
{p=2, a=5, r=1, s=1, e=2, g=1, l=1, n=3, o=1}`
Run Code Online (Sandbox Code Playgroud)
期望的输出:
{a=5, n=3, e=2, p=2, g=1, l=1, r=1, s=1, o=1}
Run Code Online (Sandbox Code Playgroud)
不可避免地要分两个映射步骤进行,因为您首先需要计数,然后才能根据计数进行排序:
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);
Run Code Online (Sandbox Code Playgroud)
如果您假设只有 ASCII 小写字母(或任何其他固定大小的小字符集),您可以尝试一种可能更有效的替代方法。它将处理字符和计数作为原始值,存储在固定大小的数组中。对象只为最后的排序和Map生成而生成:
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);
Run Code Online (Sandbox Code Playgroud)
您不能按地图的值对地图进行排序。我认为您能实现的最好是将排序的条目存储到 LinkedHashMap 中,这样当您迭代其他条目时,您将获得预期的结果(因为您将以所需的排序顺序添加映射)。
为此,您需要第一个 group by 操作来了解如何构建映射“字母 -> 出现次数”(您也可以考虑 a Map<Character, Long>)。
然后,您必须再次迭代条目集,并对流进行排序,以便条目首先按其值排序,然后按键的自然顺序排序。所以比较器看起来像:
//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());
Run Code Online (Sandbox Code Playgroud)
将这些部分放在一起,可以得到:
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));
Run Code Online (Sandbox Code Playgroud)
其产生:
{a=5, n=3, e=2, p=2, g=1, l=1, o=1, r=1, s=1}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1984 次 |
| 最近记录: |