Transform a List to a Map such that the String is not a duplicate value using Java 8 Streams












7















We have a Student class as follows:



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

}


We have a LIST of Students as follows :



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


This List needs to be converted into a HashMap<String,Integer> such that:




  1. the map does not contain any duplicate Student

  2. if a duplicate student name is found, his marks shall be added with
    the previous occurrence.


So the output should be :
{ABC = 67, DEF = 40}





I have tried to solve this issue as follows:



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


But the merge function does not allow me to concatenate the marks and this returns the output as



So the output should be :
{abc= 30, DEF = 40}



Can someone suggest an efficient solution for this?










share|improve this question





























    7















    We have a Student class as follows:



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

    }


    We have a LIST of Students as follows :



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


    This List needs to be converted into a HashMap<String,Integer> such that:




    1. the map does not contain any duplicate Student

    2. if a duplicate student name is found, his marks shall be added with
      the previous occurrence.


    So the output should be :
    {ABC = 67, DEF = 40}





    I have tried to solve this issue as follows:



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


    But the merge function does not allow me to concatenate the marks and this returns the output as



    So the output should be :
    {abc= 30, DEF = 40}



    Can someone suggest an efficient solution for this?










    share|improve this question



























      7












      7








      7








      We have a Student class as follows:



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

      }


      We have a LIST of Students as follows :



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


      This List needs to be converted into a HashMap<String,Integer> such that:




      1. the map does not contain any duplicate Student

      2. if a duplicate student name is found, his marks shall be added with
        the previous occurrence.


      So the output should be :
      {ABC = 67, DEF = 40}





      I have tried to solve this issue as follows:



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


      But the merge function does not allow me to concatenate the marks and this returns the output as



      So the output should be :
      {abc= 30, DEF = 40}



      Can someone suggest an efficient solution for this?










      share|improve this question
















      We have a Student class as follows:



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

      }


      We have a LIST of Students as follows :



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


      This List needs to be converted into a HashMap<String,Integer> such that:




      1. the map does not contain any duplicate Student

      2. if a duplicate student name is found, his marks shall be added with
        the previous occurrence.


      So the output should be :
      {ABC = 67, DEF = 40}





      I have tried to solve this issue as follows:



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


      But the merge function does not allow me to concatenate the marks and this returns the output as



      So the output should be :
      {abc= 30, DEF = 40}



      Can someone suggest an efficient solution for this?







      java list hashmap java-stream collectors






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 20 at 13:55









      Eran

      284k37462550




      284k37462550










      asked Jan 20 at 7:21









      Bibek Kr. BazazBibek Kr. Bazaz

      578




      578
























          3 Answers
          3






          active

          oldest

          votes


















          8














          That's because of an incorrect merge function, you should instead use :



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





          share|improve this answer































            6














            An alternative solution is to use groupingBy with summingInt:



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





            share|improve this answer































              4














              Your merge function is incorrect. It could be either (s1, s2) -> s1 + s2 or just Integer::sum if you'd rather use a method reference.



              Another way to do it is without streams:



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


              This iterates the list of students and uses the Map.merge method to group them by name, summing their marks.






              share|improve this answer























                Your Answer






                StackExchange.ifUsing("editor", function () {
                StackExchange.using("externalEditor", function () {
                StackExchange.using("snippets", function () {
                StackExchange.snippets.init();
                });
                });
                }, "code-snippets");

                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "1"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                autoActivateHeartbeat: false,
                convertImagesToLinks: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                draft saved

                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54274392%2ftransform-a-listobject-to-a-mapstring-integer-such-that-the-string-is-not-a%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                3 Answers
                3






                active

                oldest

                votes








                3 Answers
                3






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                8














                That's because of an incorrect merge function, you should instead use :



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





                share|improve this answer




























                  8














                  That's because of an incorrect merge function, you should instead use :



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





                  share|improve this answer


























                    8












                    8








                    8







                    That's because of an incorrect merge function, you should instead use :



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





                    share|improve this answer













                    That's because of an incorrect merge function, you should instead use :



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






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Jan 20 at 7:24









                    nullpointernullpointer

                    48.4k11101195




                    48.4k11101195

























                        6














                        An alternative solution is to use groupingBy with summingInt:



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





                        share|improve this answer




























                          6














                          An alternative solution is to use groupingBy with summingInt:



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





                          share|improve this answer


























                            6












                            6








                            6







                            An alternative solution is to use groupingBy with summingInt:



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





                            share|improve this answer













                            An alternative solution is to use groupingBy with summingInt:



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






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Jan 20 at 9:33









                            EranEran

                            284k37462550




                            284k37462550























                                4














                                Your merge function is incorrect. It could be either (s1, s2) -> s1 + s2 or just Integer::sum if you'd rather use a method reference.



                                Another way to do it is without streams:



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


                                This iterates the list of students and uses the Map.merge method to group them by name, summing their marks.






                                share|improve this answer




























                                  4














                                  Your merge function is incorrect. It could be either (s1, s2) -> s1 + s2 or just Integer::sum if you'd rather use a method reference.



                                  Another way to do it is without streams:



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


                                  This iterates the list of students and uses the Map.merge method to group them by name, summing their marks.






                                  share|improve this answer


























                                    4












                                    4








                                    4







                                    Your merge function is incorrect. It could be either (s1, s2) -> s1 + s2 or just Integer::sum if you'd rather use a method reference.



                                    Another way to do it is without streams:



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


                                    This iterates the list of students and uses the Map.merge method to group them by name, summing their marks.






                                    share|improve this answer













                                    Your merge function is incorrect. It could be either (s1, s2) -> s1 + s2 or just Integer::sum if you'd rather use a method reference.



                                    Another way to do it is without streams:



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


                                    This iterates the list of students and uses the Map.merge method to group them by name, summing their marks.







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Jan 21 at 3:15









                                    Federico Peralta SchaffnerFederico Peralta Schaffner

                                    23.1k43675




                                    23.1k43675






























                                        draft saved

                                        draft discarded




















































                                        Thanks for contributing an answer to Stack Overflow!


                                        • Please be sure to answer the question. Provide details and share your research!

                                        But avoid



                                        • Asking for help, clarification, or responding to other answers.

                                        • Making statements based on opinion; back them up with references or personal experience.


                                        To learn more, see our tips on writing great answers.




                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function () {
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54274392%2ftransform-a-listobject-to-a-mapstring-integer-such-that-the-string-is-not-a%23new-answer', 'question_page');
                                        }
                                        );

                                        Post as a guest















                                        Required, but never shown





















































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown

































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown







                                        Popular posts from this blog

                                        Liquibase includeAll doesn't find base path

                                        How to use setInterval in EJS file?

                                        Petrus Granier-Deferre