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

000*_*000 20 java list java-8 java-stream

我有两个结构如下的类:

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

public class Person {
     private String tag;
     ...
     public String getTag() {
          return tag;
     }
     ...
}
Run Code Online (Sandbox Code Playgroud)

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

如果我得到Person对象的List,有没有办法使用来自Java 8的Stream来找到所有Person对象中最常见的一个Tag值(如果是平局,可能只是最随机的一个)共同)?

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

hol*_*ava 26

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);
Run Code Online (Sandbox Code Playgroud)

并且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);
Run Code Online (Sandbox Code Playgroud)


Ste*_*ase 5

这应该适合你:

private void run() {
    List<Person> list = Arrays.asList(() -> "foo", () -> "foo", () -> "foo",
                                      () -> "bar", () -> "bar");
    Map<String, Long> commonness = list.stream()
            .collect(Collectors.groupingBy(Person::getTag, Collectors.counting()));
    Optional<String> mostCommon = commonness.entrySet().stream()
            .max(Map.Entry.comparingByValue())
            .map(Map.Entry::getKey);
    System.out.println(mostCommon.orElse("no elements in list"));
}

public interface Person {
    String getTag();
}
Run Code Online (Sandbox Code Playgroud)

commonness地图包含标签被发现多久的信息.该变量mostCommon包含最常找到的标记.另外,mostCommon是空的,如果原来的列表是空的.


chr*_*con 5

您可以将计数收集到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);
Run Code Online (Sandbox Code Playgroud)


Don*_*aab 5

如果你是开放的使用第三方库,你可以使用Collectors2Eclipse的集合与Java 8 Stream创建Bag和要求topOccurrences,这将返回MutableListObjectIntPair是标签值和出现次数的计数.

MutableList<ObjectIntPair<String>> topOccurrences = company.getPerson()
        .stream()
        .map(Person::getTag)
        .collect(Collectors2.toBag())
        .topOccurrences(1);
String mostCommonTag = topOccurrences.getFirst().getOne();
Run Code Online (Sandbox Code Playgroud)

在平局的情况下,MutableList将有多个结果.

注意:我是Eclipse Collections的提交者.