使用Stream

时间:2017-04-25 16:39:12

标签: 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;
     }
     ...
}

基本上,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?
}

6 个答案:

答案 0 :(得分:24)

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

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

答案 1 :(得分:5)

这应该适合你:

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(); 为空。

答案 2 :(得分: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);

答案 3 :(得分:5)

如果您愿意使用第三方库,则可以使用Collectors2中的Eclipse Collections与Java 8 class Boy(Person): def __init__(self, first_name, last_name, height): super(Person, self).__init__(first_name, last_name) self.height = height 创建Stream并请求{ {1}},它将返回Bag topOccurrences,这是标记值和出现次数的计数。

MutableList

如果是平局,ObjectIntPair将有多个结果。

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

答案 4 :(得分:3)

这对你有帮助,

Expire

答案 5 :(得分:3)

AbacusUtil

的另一个解决方案
// 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();