使用 Stream 从对象列表中查找最常用的属性值

2022-09-02 02:41:15

我有两个类的结构如下:

public class Company {
     private List<Person> person;
     ...
     public List<Person> getPerson() {
          return person;
     }
     ...
}

public class Person {
     private String tag;
     ...
     public String getTag() {
          return tag;
     }
     ...
}

基本上,Company 类有一个 Person 对象列表,每个 Person 对象都可以获取一个 Tag 值。

如果我得到 Person 对象的列表,有没有办法使用 Java 8 中的 Stream 来查找一个在所有 Person 对象中最常见的 Tag 值(如果出现平局,也许只是最常见的随机值)?

String mostCommonTag;
if(!company.getPerson().isEmpty) {
     mostCommonTag = company.getPerson().stream() //How to do this in Stream?
}

答案 1
String mostCommonTag = getPerson().stream()
        // filter some person without a tag out 
        .filter(it -> Objects.nonNull(it.getTag()))
        // summarize tags
        .collect(Collectors.groupingBy(Person::getTag, Collectors.counting()))
        // fetch the max entry
        .entrySet().stream().max(Map.Entry.comparingByValue())
        // map to tag
        .map(Map.Entry::getKey).orElse(null);

并且该方法出现了两次,您可以进一步简化代码:getTag

String mostCommonTag = getPerson().stream()
        // map person to tag & filter null tag out 
        .map(Person::getTag).filter(Objects::nonNull)
        // summarize tags
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
        // fetch the max entry
        .entrySet().stream().max(Map.Entry.comparingByValue())
        // map to tag
        .map(Map.Entry::getKey).orElse(null);

答案 2

您可以将计数收集到 Map 中,然后获取具有最高值的键

List<String> foo = Arrays.asList("a","b","c","d","e","e","e","f","f","f","g");
Map<String, Long> f = foo
    .stream()
    .collect(Collectors.groupingBy(v -> v, Collectors.counting()));
String maxOccurence = 
            Collections.max(f.entrySet(), Comparator.comparing(Map.Entry::getValue)).getKey();

System.out.println(maxOccurence);