查找字符串的最大出现 - Tie案例

时间:2016-07-28 00:12:46

标签: java java-8 java-stream

我有一个对象列表List listOfStudents: 对象:

private class Students
{
  private String name;
  private int numberOfTimesComeToSchool;
}

我正在尝试查找出现次数最多的学生的名字并按照我的用法进行操作:

listOfStudents.stream().map(Student::getName)collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

如果没有领带,那么我使用

Collections.max(collect.entrySet(), Map.Entry.comparingByValue()).getKey();

确定发生次数最多的名称。

但是可能会发生学生姓名的关系,在这种情况下,我想选择最多次上学的学生姓名,即有学生姓名的学生姓名。所有名称中numberOfTimesComeToSchool的最高总和。

例如:

Student 1: Name: Hello numberOfTimesComeToSchool: 1
Student 2: Name: Hello numberOfTimesComeToSchool: 4
Student 3: Name: Trial numberOfTimesComeToSchool: 2
Student 4: Name: Trial numberOfTimesComeToSchool: 2
Student 5: Name: NeedThis numberOfTimesComeToSchool: 2
Student 6: Name: NeedThis numberOfTimesComeToSchool: 2

在这种情况下,正确的答案是Hello,因为numberOfTimesComeToSchool的总和是5,而其他名称的总和只有4,即使所有名称出现的次数相同。

任何有关这方面的帮助都会被批评。

1 个答案:

答案 0 :(得分:3)

使用.map(Student::getName)的问题是,您丢失了有关每个学生上学次数的信息。

相反,只需在原始列表中使用groupingBy即可获得Map<String, List<Student>>。然后遍历地图的入口集,并通过首先比较列表的大小来找到最大条目,然后在出现平局的情况下比较numberOfTimesComeToSchool的总和。

Map<String, List<Student>> map =
        listOfStudents.stream().collect(Collectors.groupingBy(Student::getName));

Optional<String> studentName =
        map.entrySet()
           .stream()
           .max(Comparator.<Map.Entry<String, List<Student>>>comparingInt(e -> e.getValue().size())
                          .thenComparingInt(e -> e.getValue().stream().mapToInt(Student::getNumberOfTimesComeToSchool).sum()))
           .map(Map.Entry::getKey);

类型推断还不够强大,所以你必须在比较器中指定类型参数,这使得它很难阅读。

最后,您可以使用Collectors.collectingAndThen

将其设为单行
Optional<String> studentName =
    listOfStudents.stream()
                  .collect(collectingAndThen(groupingBy(Student::getName),
                                                        m -> m.entrySet()
                                                              .stream()
                                                              .max(Comparator.<Map.Entry<String, List<Student>>>comparingInt(e -> e.getValue().size())
                                                                             .thenComparingInt(e -> e.getValue().stream().mapToInt(Student::getNumberOfTimesComeToSchool).sum()))
                                                              .map(Map.Entry::getKey)));