How do I deal with null and duplicate values in a Java 8 Comparator?











up vote
10
down vote

favorite
2












I have a Photo object:



public class Photo {
@Id
private String id;
private LocalDateTime created;
private Integer poNumber;
}


poNumber can be null for some photos or all photos in a set. I want to sort a set of photos according to poNumber, so that the lowest poNumber appears first in the sorted set. poNumber may also be duplicated in the set. If poNumber is duplicated then sort according to created (earliest created photo appears first). If poNumber is null then sort according to created.



I tried the below code:



Set<Photo> orderedPhotos = new TreeSet<>(
Comparator.nullsFirst(Comparator.comparing(Photo::getPoNumber))
.thenComparing(Photo::getCreated));

for (Photo photo : unOrderedPhotos) {
orderedPhotos.add(photo);
}


But it throws a NullPointerException whenever poNumber is null. If poNumber is not null then it works fine. How can I solve this issue?










share|improve this question




















  • 1




    Where should elements with poNumber = null go? After or before the elements with a non-null value in that field?
    – Federico Peralta Schaffner
    23 hours ago















up vote
10
down vote

favorite
2












I have a Photo object:



public class Photo {
@Id
private String id;
private LocalDateTime created;
private Integer poNumber;
}


poNumber can be null for some photos or all photos in a set. I want to sort a set of photos according to poNumber, so that the lowest poNumber appears first in the sorted set. poNumber may also be duplicated in the set. If poNumber is duplicated then sort according to created (earliest created photo appears first). If poNumber is null then sort according to created.



I tried the below code:



Set<Photo> orderedPhotos = new TreeSet<>(
Comparator.nullsFirst(Comparator.comparing(Photo::getPoNumber))
.thenComparing(Photo::getCreated));

for (Photo photo : unOrderedPhotos) {
orderedPhotos.add(photo);
}


But it throws a NullPointerException whenever poNumber is null. If poNumber is not null then it works fine. How can I solve this issue?










share|improve this question




















  • 1




    Where should elements with poNumber = null go? After or before the elements with a non-null value in that field?
    – Federico Peralta Schaffner
    23 hours ago













up vote
10
down vote

favorite
2









up vote
10
down vote

favorite
2






2





I have a Photo object:



public class Photo {
@Id
private String id;
private LocalDateTime created;
private Integer poNumber;
}


poNumber can be null for some photos or all photos in a set. I want to sort a set of photos according to poNumber, so that the lowest poNumber appears first in the sorted set. poNumber may also be duplicated in the set. If poNumber is duplicated then sort according to created (earliest created photo appears first). If poNumber is null then sort according to created.



I tried the below code:



Set<Photo> orderedPhotos = new TreeSet<>(
Comparator.nullsFirst(Comparator.comparing(Photo::getPoNumber))
.thenComparing(Photo::getCreated));

for (Photo photo : unOrderedPhotos) {
orderedPhotos.add(photo);
}


But it throws a NullPointerException whenever poNumber is null. If poNumber is not null then it works fine. How can I solve this issue?










share|improve this question















I have a Photo object:



public class Photo {
@Id
private String id;
private LocalDateTime created;
private Integer poNumber;
}


poNumber can be null for some photos or all photos in a set. I want to sort a set of photos according to poNumber, so that the lowest poNumber appears first in the sorted set. poNumber may also be duplicated in the set. If poNumber is duplicated then sort according to created (earliest created photo appears first). If poNumber is null then sort according to created.



I tried the below code:



Set<Photo> orderedPhotos = new TreeSet<>(
Comparator.nullsFirst(Comparator.comparing(Photo::getPoNumber))
.thenComparing(Photo::getCreated));

for (Photo photo : unOrderedPhotos) {
orderedPhotos.add(photo);
}


But it throws a NullPointerException whenever poNumber is null. If poNumber is not null then it works fine. How can I solve this issue?







java java-8 comparator






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 9 hours ago









Boann

36.5k1286119




36.5k1286119










asked yesterday









ace

5,9922674128




5,9922674128








  • 1




    Where should elements with poNumber = null go? After or before the elements with a non-null value in that field?
    – Federico Peralta Schaffner
    23 hours ago














  • 1




    Where should elements with poNumber = null go? After or before the elements with a non-null value in that field?
    – Federico Peralta Schaffner
    23 hours ago








1




1




Where should elements with poNumber = null go? After or before the elements with a non-null value in that field?
– Federico Peralta Schaffner
23 hours ago




Where should elements with poNumber = null go? After or before the elements with a non-null value in that field?
– Federico Peralta Schaffner
23 hours ago












4 Answers
4






active

oldest

votes

















up vote
6
down vote



accepted










You can use a two-argument Comparator.comparing overload, for example:



import static java.util.Comparator.*; // for the sake of brevity

Set<Photo> orderedPhotos = new TreeSet<>(
Comparator.comparing(Photo::getPoNumber, nullsFirst(naturalOrder()))
.thenComparing(Photo::getCreated));





share|improve this answer






























    up vote
    8
    down vote













    We need a solution which turns the Function<> to a Comparator, but in a way which adds the said null checking to the chain.



    And that's where Oleksandr's answer enters the scene: it creates a Comparator which maps the compared Photo to comparing of Integers, and then adds a Comparator which naturally orders these Integers with the nulls first:



    Comparator.comparing(Photo::getPoNumber, Comparator.nullsFirst(Comparator.naturalOrder()))


    And this comparator is then chained (for the case of equality) with another comparator which considers the creation date.






    share|improve this answer






























      up vote
      2
      down vote













      The way you have written it, the Photo key could be null but nothing else.



      Comparator.nullsFirst( // Photo could be null.
      Comparator.comparing(Comparator.nullsFirst(Photo::getPoNumber)) // poNumber could be null.
      .thenComparing(Comparator.nullsFirst(Photo::getCreated))) // created could be null


      If any of these can't be null you can remove the Comparator.nullsFirst






      share|improve this answer



















      • 4




        "But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention of created being able to be null.
        – glglgl
        yesterday


















      up vote
      1
      down vote













      This will put null values at the beginning



      Integer getPoNumber() { return poNumber == null ? Integer.MIN_VALUE : poNumber };


      This will put null values at the end



      Integer getPoNumber() { return poNumber == null ? Integer.MAX_VALUE: poNumber };


      Otherwise, implement your own comparator to handle the null values






      share|improve this answer























      • I dislike Integer so would return int in this case. ;)
        – Peter Lawrey
        yesterday










      • Its what he's using, but yeah... @ace , Integer.intValue();
        – Joseph D
        yesterday











      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',
      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%2f53337345%2fhow-do-i-deal-with-null-and-duplicate-values-in-a-java-8-comparator%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








      up vote
      6
      down vote



      accepted










      You can use a two-argument Comparator.comparing overload, for example:



      import static java.util.Comparator.*; // for the sake of brevity

      Set<Photo> orderedPhotos = new TreeSet<>(
      Comparator.comparing(Photo::getPoNumber, nullsFirst(naturalOrder()))
      .thenComparing(Photo::getCreated));





      share|improve this answer



























        up vote
        6
        down vote



        accepted










        You can use a two-argument Comparator.comparing overload, for example:



        import static java.util.Comparator.*; // for the sake of brevity

        Set<Photo> orderedPhotos = new TreeSet<>(
        Comparator.comparing(Photo::getPoNumber, nullsFirst(naturalOrder()))
        .thenComparing(Photo::getCreated));





        share|improve this answer

























          up vote
          6
          down vote



          accepted







          up vote
          6
          down vote



          accepted






          You can use a two-argument Comparator.comparing overload, for example:



          import static java.util.Comparator.*; // for the sake of brevity

          Set<Photo> orderedPhotos = new TreeSet<>(
          Comparator.comparing(Photo::getPoNumber, nullsFirst(naturalOrder()))
          .thenComparing(Photo::getCreated));





          share|improve this answer














          You can use a two-argument Comparator.comparing overload, for example:



          import static java.util.Comparator.*; // for the sake of brevity

          Set<Photo> orderedPhotos = new TreeSet<>(
          Comparator.comparing(Photo::getPoNumber, nullsFirst(naturalOrder()))
          .thenComparing(Photo::getCreated));






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 15 hours ago

























          answered yesterday









          Oleksandr

          7,72543467




          7,72543467
























              up vote
              8
              down vote













              We need a solution which turns the Function<> to a Comparator, but in a way which adds the said null checking to the chain.



              And that's where Oleksandr's answer enters the scene: it creates a Comparator which maps the compared Photo to comparing of Integers, and then adds a Comparator which naturally orders these Integers with the nulls first:



              Comparator.comparing(Photo::getPoNumber, Comparator.nullsFirst(Comparator.naturalOrder()))


              And this comparator is then chained (for the case of equality) with another comparator which considers the creation date.






              share|improve this answer



























                up vote
                8
                down vote













                We need a solution which turns the Function<> to a Comparator, but in a way which adds the said null checking to the chain.



                And that's where Oleksandr's answer enters the scene: it creates a Comparator which maps the compared Photo to comparing of Integers, and then adds a Comparator which naturally orders these Integers with the nulls first:



                Comparator.comparing(Photo::getPoNumber, Comparator.nullsFirst(Comparator.naturalOrder()))


                And this comparator is then chained (for the case of equality) with another comparator which considers the creation date.






                share|improve this answer

























                  up vote
                  8
                  down vote










                  up vote
                  8
                  down vote









                  We need a solution which turns the Function<> to a Comparator, but in a way which adds the said null checking to the chain.



                  And that's where Oleksandr's answer enters the scene: it creates a Comparator which maps the compared Photo to comparing of Integers, and then adds a Comparator which naturally orders these Integers with the nulls first:



                  Comparator.comparing(Photo::getPoNumber, Comparator.nullsFirst(Comparator.naturalOrder()))


                  And this comparator is then chained (for the case of equality) with another comparator which considers the creation date.






                  share|improve this answer














                  We need a solution which turns the Function<> to a Comparator, but in a way which adds the said null checking to the chain.



                  And that's where Oleksandr's answer enters the scene: it creates a Comparator which maps the compared Photo to comparing of Integers, and then adds a Comparator which naturally orders these Integers with the nulls first:



                  Comparator.comparing(Photo::getPoNumber, Comparator.nullsFirst(Comparator.naturalOrder()))


                  And this comparator is then chained (for the case of equality) with another comparator which considers the creation date.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 19 hours ago


























                  community wiki





                  4 revs, 2 users 65%
                  glglgl























                      up vote
                      2
                      down vote













                      The way you have written it, the Photo key could be null but nothing else.



                      Comparator.nullsFirst( // Photo could be null.
                      Comparator.comparing(Comparator.nullsFirst(Photo::getPoNumber)) // poNumber could be null.
                      .thenComparing(Comparator.nullsFirst(Photo::getCreated))) // created could be null


                      If any of these can't be null you can remove the Comparator.nullsFirst






                      share|improve this answer



















                      • 4




                        "But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention of created being able to be null.
                        – glglgl
                        yesterday















                      up vote
                      2
                      down vote













                      The way you have written it, the Photo key could be null but nothing else.



                      Comparator.nullsFirst( // Photo could be null.
                      Comparator.comparing(Comparator.nullsFirst(Photo::getPoNumber)) // poNumber could be null.
                      .thenComparing(Comparator.nullsFirst(Photo::getCreated))) // created could be null


                      If any of these can't be null you can remove the Comparator.nullsFirst






                      share|improve this answer



















                      • 4




                        "But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention of created being able to be null.
                        – glglgl
                        yesterday













                      up vote
                      2
                      down vote










                      up vote
                      2
                      down vote









                      The way you have written it, the Photo key could be null but nothing else.



                      Comparator.nullsFirst( // Photo could be null.
                      Comparator.comparing(Comparator.nullsFirst(Photo::getPoNumber)) // poNumber could be null.
                      .thenComparing(Comparator.nullsFirst(Photo::getCreated))) // created could be null


                      If any of these can't be null you can remove the Comparator.nullsFirst






                      share|improve this answer














                      The way you have written it, the Photo key could be null but nothing else.



                      Comparator.nullsFirst( // Photo could be null.
                      Comparator.comparing(Comparator.nullsFirst(Photo::getPoNumber)) // poNumber could be null.
                      .thenComparing(Comparator.nullsFirst(Photo::getCreated))) // created could be null


                      If any of these can't be null you can remove the Comparator.nullsFirst







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited yesterday

























                      answered yesterday









                      Peter Lawrey

                      436k55548945




                      436k55548945








                      • 4




                        "But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention of created being able to be null.
                        – glglgl
                        yesterday














                      • 4




                        "But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention of created being able to be null.
                        – glglgl
                        yesterday








                      4




                      4




                      "But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention of created being able to be null.
                      – glglgl
                      yesterday




                      "But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention of created being able to be null.
                      – glglgl
                      yesterday










                      up vote
                      1
                      down vote













                      This will put null values at the beginning



                      Integer getPoNumber() { return poNumber == null ? Integer.MIN_VALUE : poNumber };


                      This will put null values at the end



                      Integer getPoNumber() { return poNumber == null ? Integer.MAX_VALUE: poNumber };


                      Otherwise, implement your own comparator to handle the null values






                      share|improve this answer























                      • I dislike Integer so would return int in this case. ;)
                        – Peter Lawrey
                        yesterday










                      • Its what he's using, but yeah... @ace , Integer.intValue();
                        – Joseph D
                        yesterday















                      up vote
                      1
                      down vote













                      This will put null values at the beginning



                      Integer getPoNumber() { return poNumber == null ? Integer.MIN_VALUE : poNumber };


                      This will put null values at the end



                      Integer getPoNumber() { return poNumber == null ? Integer.MAX_VALUE: poNumber };


                      Otherwise, implement your own comparator to handle the null values






                      share|improve this answer























                      • I dislike Integer so would return int in this case. ;)
                        – Peter Lawrey
                        yesterday










                      • Its what he's using, but yeah... @ace , Integer.intValue();
                        – Joseph D
                        yesterday













                      up vote
                      1
                      down vote










                      up vote
                      1
                      down vote









                      This will put null values at the beginning



                      Integer getPoNumber() { return poNumber == null ? Integer.MIN_VALUE : poNumber };


                      This will put null values at the end



                      Integer getPoNumber() { return poNumber == null ? Integer.MAX_VALUE: poNumber };


                      Otherwise, implement your own comparator to handle the null values






                      share|improve this answer














                      This will put null values at the beginning



                      Integer getPoNumber() { return poNumber == null ? Integer.MIN_VALUE : poNumber };


                      This will put null values at the end



                      Integer getPoNumber() { return poNumber == null ? Integer.MAX_VALUE: poNumber };


                      Otherwise, implement your own comparator to handle the null values







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited yesterday

























                      answered yesterday









                      Joseph D

                      374110




                      374110












                      • I dislike Integer so would return int in this case. ;)
                        – Peter Lawrey
                        yesterday










                      • Its what he's using, but yeah... @ace , Integer.intValue();
                        – Joseph D
                        yesterday


















                      • I dislike Integer so would return int in this case. ;)
                        – Peter Lawrey
                        yesterday










                      • Its what he's using, but yeah... @ace , Integer.intValue();
                        – Joseph D
                        yesterday
















                      I dislike Integer so would return int in this case. ;)
                      – Peter Lawrey
                      yesterday




                      I dislike Integer so would return int in this case. ;)
                      – Peter Lawrey
                      yesterday












                      Its what he's using, but yeah... @ace , Integer.intValue();
                      – Joseph D
                      yesterday




                      Its what he's using, but yeah... @ace , Integer.intValue();
                      – Joseph D
                      yesterday


















                       

                      draft saved


                      draft discarded



















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337345%2fhow-do-i-deal-with-null-and-duplicate-values-in-a-java-8-comparator%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

                      "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                      Alcedinidae

                      RAC Tourist Trophy