Java-Stream - Java 11 中基于聚合计数的分组和排序

Sar*_*tty 2 java sorting java-stream

我有一个Stream自定义对象作为方法的参数。显然我只能使用一次 Stream。

我的对象有一个String名为 的属性category

public class MyType {
    private String category;
    
    // other properties, getters, etc.
}
Run Code Online (Sandbox Code Playgroud)

我需要一个分类列表List<String>

首先,我需要根据每个类别出现的次数对数据进行排序。如果出现次数相同,则按字典顺序对这些类别进行排序。

基本上,我需要这样的东西

java8流对聚合和进行分组和排序

我没有办法多次消费该流。所以我不知道如何解决这个问题。

这是一个例子:

输入:

{
    object1 :{category:"category1"},
    object2 :{category:"categoryB"},
    object3 :{category:"categoryA"},
    object4 :{category:"category1"},
    object5 :{category:"categoryB"},
    object6 :{category:"category1"},
    object7 :{category:"categoryA"}
}
Run Code Online (Sandbox Code Playgroud)

输出:

List = {category1, categoryA, categoryB}
Run Code Online (Sandbox Code Playgroud)

Ale*_*nko 5

您可以为每个类型类别生成频率图Map<String,Long>按类别计数)。

然后在其条目上创建一个流并对它们进行排序(按值,即按计数,按键,即按字典顺序),从每个条目中提取类别并将结果存储到列表中。

假设您有以下域类型:

public class MyType {
    private String category;
    
    // getters
}
Run Code Online (Sandbox Code Playgroud)

生成类别排序列表的方法可以像这样实现:

public static List<String> getSortedCategories(Stream<MyType> stream) {
    
    return stream.collect(Collectors.groupingBy(
            MyType::getCategory,
            Collectors.counting()
        ))
        .entrySet().stream()
        .sorted(
            Map.Entry.<String, Long>comparingByValue()
                .thenComparing(Map.Entry.comparingByKey())
        )
        .map(Map.Entry::getKey)
        .toList();
}
Run Code Online (Sandbox Code Playgroud)