6
votes

Transformez une liste en une carte de sorte que la chaîne ne soit pas une valeur dupliquée à l'aide de Java 8 Streams

Nous avons une classe d'étudiants comme suit:

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

Nous avons une LISTE d'étudiants comme suit:

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

Cette liste doit être converti en HashMap tel que:

  1. la carte ne contient aucun étudiant en double
  2. si un nom d'étudiant en double est trouvé, ses notes seront ajoutées avec l'occurrence précédente.

Le résultat devrait donc être: {ABC = 67, DEF = 40}


J'ai essayé de résoudre ce problème comme suit:

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

}

Mais la fonction de fusion ne fonctionne pas permettez-moi de concaténer les marques et cela renvoie la sortie comme

Donc la sortie devrait être: {abc = 30, DEF = 40}

Quelqu'un peut-il suggérer une solution efficace pour cela?


0 commentaires

3 Réponses :


6
votes

En raison d'une fonction de fusion incorrecte, vous devez utiliser à la place:

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


0 commentaires

5
votes

Une autre solution consiste à utiliser groupingBy avec summingInt:

Map<String, Integer> studentMap = 
    studentList.stream()
               .collect(Collectors.groupingBy(s -> s.getStudentName().toLowerCase(),
                                              Collectors.summingInt(Student::getMarks)));


0 commentaires

3
votes

Votre fonction de fusion est incorrecte. Il peut s'agir de (s1, s2) -> s1 + s2 ou simplement de Integer :: sum si vous préférez utiliser une référence de méthode.

Une autre façon de faites-le sans flux:

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

Ceci itère la liste des élèves et utilise la méthode Map.merge pour les regrouper par nom, en additionnant leurs notes .


0 commentaires