Finding duplicated objects by two properties












1















Considering that I have a list of Person objects like this :



Class Person {
String fullName;
String occupation;
String hobby;
int salary;
}


Using java8 streams, how can I get list of duplicated objects only by fullName and occupation property?










share|improve this question























  • add equals and hashCode in person class?

    – SMA
    Nov 15 '18 at 7:19






  • 1





    Have you checked out Java 8 Distinct by property ?

    – Jorn Vernee
    Nov 15 '18 at 7:22








  • 1





    Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.

    – kkot
    Nov 15 '18 at 7:25
















1















Considering that I have a list of Person objects like this :



Class Person {
String fullName;
String occupation;
String hobby;
int salary;
}


Using java8 streams, how can I get list of duplicated objects only by fullName and occupation property?










share|improve this question























  • add equals and hashCode in person class?

    – SMA
    Nov 15 '18 at 7:19






  • 1





    Have you checked out Java 8 Distinct by property ?

    – Jorn Vernee
    Nov 15 '18 at 7:22








  • 1





    Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.

    – kkot
    Nov 15 '18 at 7:25














1












1








1








Considering that I have a list of Person objects like this :



Class Person {
String fullName;
String occupation;
String hobby;
int salary;
}


Using java8 streams, how can I get list of duplicated objects only by fullName and occupation property?










share|improve this question














Considering that I have a list of Person objects like this :



Class Person {
String fullName;
String occupation;
String hobby;
int salary;
}


Using java8 streams, how can I get list of duplicated objects only by fullName and occupation property?







java java-8






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 15 '18 at 7:17









kkotkkot

387




387













  • add equals and hashCode in person class?

    – SMA
    Nov 15 '18 at 7:19






  • 1





    Have you checked out Java 8 Distinct by property ?

    – Jorn Vernee
    Nov 15 '18 at 7:22








  • 1





    Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.

    – kkot
    Nov 15 '18 at 7:25



















  • add equals and hashCode in person class?

    – SMA
    Nov 15 '18 at 7:19






  • 1





    Have you checked out Java 8 Distinct by property ?

    – Jorn Vernee
    Nov 15 '18 at 7:22








  • 1





    Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.

    – kkot
    Nov 15 '18 at 7:25

















add equals and hashCode in person class?

– SMA
Nov 15 '18 at 7:19





add equals and hashCode in person class?

– SMA
Nov 15 '18 at 7:19




1




1





Have you checked out Java 8 Distinct by property ?

– Jorn Vernee
Nov 15 '18 at 7:22







Have you checked out Java 8 Distinct by property ?

– Jorn Vernee
Nov 15 '18 at 7:22






1




1





Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.

– kkot
Nov 15 '18 at 7:25





Well yes. I don't need to distinct duplicates, rather I need to find if they were any duplicates in fullName - occupation pair, which has to be unique. I found plenty of topics where duplicated were removed. I need to add them.

– kkot
Nov 15 '18 at 7:25












4 Answers
4






active

oldest

votes


















3














By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation



List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
.values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());





share|improve this answer
























  • this is duplication of my answer IMHO

    – oleg.cherednik
    Nov 15 '18 at 8:03











  • but i did not copy that, did it my self and posted at same time @oleg.cherednik

    – Deadpool
    Nov 15 '18 at 8:04



















2















I need to find if they were any duplicates in fullName - occupation pair, which has to be unique




Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.



In that case you can use a stateful anyMatch:



Collection<Person> input = new ArrayList<>();

Set<List<String>> seen = new HashSet<>();
boolean hasDupes = input.stream()
.anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));


You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.






share|improve this answer

































    1














    First implement equals and hashCode in your person class and then use.



    List<Person> personList = new ArrayList<>();

    Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
    .collect(Collectors.toSet());


    If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.






    share|improve this answer































      1














      I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.



      public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
      Map<String, List<Person>> map = persons.stream()
      .collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));

      return map.values().stream()
      .filter(personList -> personList.size() > 1)
      .flatMap(List::stream)
      .collect(Collectors.toList());
      }


      Client code:



      List<Person> persons = Collections.emptyList();
      List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);





      share|improve this answer



















      • 1





        Alternatively, you may combine the filter and flatMap step: .flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be a String. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).

        – Holger
        Nov 15 '18 at 10:29













      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%2f53314218%2ffinding-duplicated-objects-by-two-properties%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      3














      By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation



      List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
      .values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());





      share|improve this answer
























      • this is duplication of my answer IMHO

        – oleg.cherednik
        Nov 15 '18 at 8:03











      • but i did not copy that, did it my self and posted at same time @oleg.cherednik

        – Deadpool
        Nov 15 '18 at 8:04
















      3














      By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation



      List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
      .values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());





      share|improve this answer
























      • this is duplication of my answer IMHO

        – oleg.cherednik
        Nov 15 '18 at 8:03











      • but i did not copy that, did it my self and posted at same time @oleg.cherednik

        – Deadpool
        Nov 15 '18 at 8:04














      3












      3








      3







      By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation



      List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
      .values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());





      share|improve this answer













      By using java-8 Stream() and Collectors.groupingBy() on firstname and occupation



      List<Person> duplicates =list.stream().collect(Collectors.groupingBy(p->p.getFullName()+"-"+p.getOccupation(),Collectors.toList()))
      .values().stream().filter(i->i.size()>1).flatMap(j->j.stream()).collect(Collectors.toList());






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Nov 15 '18 at 8:02









      DeadpoolDeadpool

      6,5892629




      6,5892629













      • this is duplication of my answer IMHO

        – oleg.cherednik
        Nov 15 '18 at 8:03











      • but i did not copy that, did it my self and posted at same time @oleg.cherednik

        – Deadpool
        Nov 15 '18 at 8:04



















      • this is duplication of my answer IMHO

        – oleg.cherednik
        Nov 15 '18 at 8:03











      • but i did not copy that, did it my self and posted at same time @oleg.cherednik

        – Deadpool
        Nov 15 '18 at 8:04

















      this is duplication of my answer IMHO

      – oleg.cherednik
      Nov 15 '18 at 8:03





      this is duplication of my answer IMHO

      – oleg.cherednik
      Nov 15 '18 at 8:03













      but i did not copy that, did it my self and posted at same time @oleg.cherednik

      – Deadpool
      Nov 15 '18 at 8:04





      but i did not copy that, did it my self and posted at same time @oleg.cherednik

      – Deadpool
      Nov 15 '18 at 8:04













      2















      I need to find if they were any duplicates in fullName - occupation pair, which has to be unique




      Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.



      In that case you can use a stateful anyMatch:



      Collection<Person> input = new ArrayList<>();

      Set<List<String>> seen = new HashSet<>();
      boolean hasDupes = input.stream()
      .anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));


      You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.






      share|improve this answer






























        2















        I need to find if they were any duplicates in fullName - occupation pair, which has to be unique




        Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.



        In that case you can use a stateful anyMatch:



        Collection<Person> input = new ArrayList<>();

        Set<List<String>> seen = new HashSet<>();
        boolean hasDupes = input.stream()
        .anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));


        You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.






        share|improve this answer




























          2












          2








          2








          I need to find if they were any duplicates in fullName - occupation pair, which has to be unique




          Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.



          In that case you can use a stateful anyMatch:



          Collection<Person> input = new ArrayList<>();

          Set<List<String>> seen = new HashSet<>();
          boolean hasDupes = input.stream()
          .anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));


          You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.






          share|improve this answer
















          I need to find if they were any duplicates in fullName - occupation pair, which has to be unique




          Based on this comment it seems that you don't really care about which Person objects were duplicated, just that there were any.



          In that case you can use a stateful anyMatch:



          Collection<Person> input = new ArrayList<>();

          Set<List<String>> seen = new HashSet<>();
          boolean hasDupes = input.stream()
          .anyMatch(p -> !seen.add(List.of(p.fullName, p.occupation)));


          You can use a List as a 'key' for a set which contains the fullName + occupation combinations that you've already seen. If this combination is seen again you immediately return true, otherwise you finish iterating the elements and return false.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 17 '18 at 12:21

























          answered Nov 15 '18 at 7:46









          Jorn VerneeJorn Vernee

          20.6k33861




          20.6k33861























              1














              First implement equals and hashCode in your person class and then use.



              List<Person> personList = new ArrayList<>();

              Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
              .collect(Collectors.toSet());


              If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.






              share|improve this answer




























                1














                First implement equals and hashCode in your person class and then use.



                List<Person> personList = new ArrayList<>();

                Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
                .collect(Collectors.toSet());


                If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.






                share|improve this answer


























                  1












                  1








                  1







                  First implement equals and hashCode in your person class and then use.



                  List<Person> personList = new ArrayList<>();

                  Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
                  .collect(Collectors.toSet());


                  If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.






                  share|improve this answer













                  First implement equals and hashCode in your person class and then use.



                  List<Person> personList = new ArrayList<>();

                  Set<Person> duplicates=personList.stream().filter(p -> Collections.frequency(personList, p) ==2)
                  .collect(Collectors.toSet());


                  If objects are more than 2 then you use Collections.frequency(personList, p) >1 in filter predicate.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 15 '18 at 7:22









                  Khalid ShahKhalid Shah

                  1,4071921




                  1,4071921























                      1














                      I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.



                      public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
                      Map<String, List<Person>> map = persons.stream()
                      .collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));

                      return map.values().stream()
                      .filter(personList -> personList.size() > 1)
                      .flatMap(List::stream)
                      .collect(Collectors.toList());
                      }


                      Client code:



                      List<Person> persons = Collections.emptyList();
                      List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);





                      share|improve this answer



















                      • 1





                        Alternatively, you may combine the filter and flatMap step: .flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be a String. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).

                        – Holger
                        Nov 15 '18 at 10:29


















                      1














                      I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.



                      public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
                      Map<String, List<Person>> map = persons.stream()
                      .collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));

                      return map.values().stream()
                      .filter(personList -> personList.size() > 1)
                      .flatMap(List::stream)
                      .collect(Collectors.toList());
                      }


                      Client code:



                      List<Person> persons = Collections.emptyList();
                      List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);





                      share|improve this answer



















                      • 1





                        Alternatively, you may combine the filter and flatMap step: .flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be a String. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).

                        – Holger
                        Nov 15 '18 at 10:29
















                      1












                      1








                      1







                      I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.



                      public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
                      Map<String, List<Person>> map = persons.stream()
                      .collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));

                      return map.values().stream()
                      .filter(personList -> personList.size() > 1)
                      .flatMap(List::stream)
                      .collect(Collectors.toList());
                      }


                      Client code:



                      List<Person> persons = Collections.emptyList();
                      List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);





                      share|improve this answer













                      I offer solution with O(n) complexity. I offer to use Map to group given list by key (fullName + occupation) and then retrieve duplicates.



                      public static List<Person> getDuplicates(List<Person> persons, Function<Person, String> classifier) {
                      Map<String, List<Person>> map = persons.stream()
                      .collect(Collectors.groupingBy(classifier, Collectors.mapping(Function.identity(), Collectors.toList())));

                      return map.values().stream()
                      .filter(personList -> personList.size() > 1)
                      .flatMap(List::stream)
                      .collect(Collectors.toList());
                      }


                      Client code:



                      List<Person> persons = Collections.emptyList();
                      List<Person> duplicates = getDuplicates(persons, person -> person.fullName + ':' + person.occupation);






                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Nov 15 '18 at 8:01









                      oleg.cherednikoleg.cherednik

                      7,10021119




                      7,10021119








                      • 1





                        Alternatively, you may combine the filter and flatMap step: .flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be a String. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).

                        – Holger
                        Nov 15 '18 at 10:29
















                      • 1





                        Alternatively, you may combine the filter and flatMap step: .flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be a String. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).

                        – Holger
                        Nov 15 '18 at 10:29










                      1




                      1





                      Alternatively, you may combine the filter and flatMap step: .flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be a String. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).

                      – Holger
                      Nov 15 '18 at 10:29







                      Alternatively, you may combine the filter and flatMap step: .flatMap(list -> list.size() > 1? list.stream(): null). But you should not force the key type to be a String. Creating the key for two properties via string concatenation is inefficient and error prone (might create clashes on the resulting strings).

                      – Holger
                      Nov 15 '18 at 10:29




















                      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%2f53314218%2ffinding-duplicated-objects-by-two-properties%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

                      The Sandy Post

                      Danny Elfman

                      Pages that link to "Head v. Amoskeag Manufacturing Co."