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

Java 使用流从对象列表中查找最常见的属性值,java,list,java-8,java-stream,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 ge

我有两个类的结构如下:

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

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

这应该适合您:

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();
}
private void run(){
List List=Arrays.asList(()->“foo”、()->“foo”、()->“foo”,
()->“酒吧”,()->“酒吧”);
Map commonness=list.stream()
.collect(Collectors.groupingBy(Person::getTag,Collectors.counting());
可选的mostCommon=commonness.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(map.Entry::getKey);
System.out.println(mostCommon.orElse(“列表中没有元素”);
}
公共接口人员{
字符串getTag();
}

commonness
地图包含找到哪个标签的频率信息。变量
mostCommon
包含最常找到的标记。另外,如果原始列表为空,
mostCommon
为空。

这对您很有帮助

Map<String, Long> count = persons.stream().collect(
                Collectors.groupingBy(Person::getTag, Collectors.counting()));

Optional<Entry<String, Long>> maxValue = count .entrySet()
        .stream().max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1).get().getKey();

maxValue.get().getValue();
Map count=persons.stream().collect(
Collectors.groupby(Person::getTag,Collectors.counting());
可选的maxValue=count.entrySet()
.stream().max((entry1,entry2)->entry1.getValue()>entry2.getValue()?1:-1.get().getKey();
maxValue.get().getValue();
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);

您可以将计数收集到一个映射,然后获取具有最高值的键

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);
List foo=array.asList(“a”、“b”、“c”、“d”、“e”、“e”、“e”、“f”、“f”、“g”);
图f=foo
.stream()
.collect(Collectors.groupingBy(v->v,Collectors.counting());
字符串MaxOccurrence=
Collections.max(f.entrySet(),Comparator.comparing(Map.Entry::getValue)).getKey();
System.out.println(maxOccurrence);

如果您愿意使用第三方库,您可以将from与Java 8
流一起使用
创建一个
,并请求
拓扑发生
,它将返回
对象对
可变列表
,它是标记值和发生次数的计数

MutableList<ObjectIntPair<String>> topOccurrences = company.getPerson()
        .stream()
        .map(Person::getTag)
        .collect(Collectors2.toBag())
        .topOccurrences(1);
String mostCommonTag = topOccurrences.getFirst().getOne();
MutableList topOccurrences=company.getPerson()
.stream()
.map(Person::getTag)
.collect(收集器2.toBag())
.拓扑发生(1);
字符串mostCommonTag=topOccurrences.getFirst().getOne();
在平局的情况下,
MutableList
将有多个结果

注意:我是Eclipse集合的提交者。

还有一个解决方案


谢谢你的详细回答。不过有一点需要澄清,我得到了一个“元素不能映射到空键”异常,因为显然有人没有标记值。我应该如何在流中处理这个问题。您也可以使用
公司
映射到该公司最常用的标记。另外,不需要
!company.getPerson().isEmpty()
等。此比较器不处理相等-虽然这可能适用于
max
,但通常这样做不是一个好主意-只需使用多种方法之一获得适当的
比较器,例如通过
比较器。comparingLong
Long::comparieto
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);
MutableList<ObjectIntPair<String>> topOccurrences = company.getPerson()
        .stream()
        .map(Person::getTag)
        .collect(Collectors2.toBag())
        .topOccurrences(1);
String mostCommonTag = topOccurrences.getFirst().getOne();
// Comparing the solution by jdk stream, 
// there is no "collect(Collectors.groupingBy(Person::getTag, Collectors.counting())).entrySet().stream"
Stream.of(company.getPerson()).map(Person::getTag).skipNull() //
        .groupBy(Fn.identity(), Collectors.counting()) //
        .max(Comparators.comparingByValue()).map(e -> e.getKey()).orNull();

// Or by multiset
Stream.of(company.getPerson()).map(Person::getTag).skipNull() //
        .toMultiset().maxOccurrences().map(e -> e.getKey()).orNull();