Преобразуйте список <Object>в карту <String, Integer>, чтобы строка не являлась дублирующим значением, используя потоки Java 8 - PullRequest
0 голосов
/ 20 января 2019

У нас есть класс ученика следующим образом:

class Student{
    private int marks;
    private String studentName;

    public int getMarks() {
        return marks;
    }

    public void setMarks(int marks) {
        this.marks = marks;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public Student(String studentName, int marks) {
        this.marks = marks;
        this.studentName = studentName;
    }

}

У нас есть СПИСОК учеников следующим образом:

List<Student> studentList = new ArrayList<>();
studentList.add(new Student("abc", 30));
studentList.add(new Student("Abc", 32));
studentList.add(new Student("ABC", 35));
studentList.add(new Student("DEF", 40));

Этот список необходимо преобразовать в HashMap<String,Integer> такойчто:

  1. карта не содержит дубликатов учащегося
  2. , если найдено повторяющееся имя учащегося, его оценки будут добавлены с предыдущим появлением.

Таким образом, выходные данные должны быть: {ABC = 67, DEF = 40}


Я попытался решить эту проблему следующим образом:

Map<String,Integer> studentMap = studentList.stream()
            .collect(
                    Collectors.toMap(
                            student->student.getStudentName().toLowerCase(),
                            student -> student.getMarks(),
                            (s1,s2) -> s1,
                            LinkedHashMap::new
                            )
            );

Но функция слияния делаетне позволяет мне объединять метки, и это возвращает вывод как

Таким образом, вывод должен быть: {abc = 30, DEF = 40}

Может кто-нибудь предложить эффективное решение для этого?

Ответы [ 3 ]

0 голосов
/ 20 января 2019

Альтернативным решением является использование groupingBy с summingInt:

Map<String, Integer> studentMap = 
    studentList.stream()
               .collect(Collectors.groupingBy(s -> s.getStudentName().toLowerCase(),
                                              Collectors.summingInt(Student::getMarks)));
0 голосов
/ 21 января 2019

Ваша функция слияния неверна. Это может быть либо (s1, s2) -> s1 + s2, либо просто Integer::sum, если вы предпочитаете использовать ссылку на метод.

Еще один способ сделать это без потоков:

Map<String, Integer> studentMap = new LinkedHashMap<>();
studentList.forEach(s -> studentMap.merge(
                         s.getStudentName().toLowerCase(),
                         s.getMarks(),
                         Integer::sum));

Это повторяет список студентов и использует метод Map.merge для группировки их по имени и суммирования их оценок.

0 голосов
/ 20 января 2019

Это из-за неправильной функции слияния, вместо этого вы должны использовать:

Map<String, Integer> map = studentList.stream()
        .collect(Collectors.toMap(
                        student->student.getStudentName().toLowerCase(),
                        Student::getMarks,
                        (s1,s2) -> s1 +s2, // add values when merging
                        LinkedHashMap::new
                ));
...