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();