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











up vote
12
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
    Nov 16 at 13:05















up vote
12
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
    Nov 16 at 13:05













up vote
12
down vote

favorite
2









up vote
12
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 Nov 17 at 3:21









Boann

36.5k1286119




36.5k1286119










asked Nov 16 at 11:52









ace

6,0072674129




6,0072674129








  • 1




    Where should elements with poNumber = null go? After or before the elements with a non-null value in that field?
    – Federico Peralta Schaffner
    Nov 16 at 13:05














  • 1




    Where should elements with poNumber = null go? After or before the elements with a non-null value in that field?
    – Federico Peralta Schaffner
    Nov 16 at 13:05








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
Nov 16 at 13:05




Where should elements with poNumber = null go? After or before the elements with a non-null value in that field?
– Federico Peralta Schaffner
Nov 16 at 13:05












4 Answers
4






active

oldest

votes

















up vote
7
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
    9
    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
      3
      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
        Nov 16 at 12:00


















      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
        Nov 16 at 12:01










      • Its what he's using, but yeah... @ace , Integer.intValue();
        – Joseph D
        Nov 16 at 12:02











      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
      7
      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
        7
        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
          7
          down vote



          accepted







          up vote
          7
          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 Nov 16 at 20:47

























          answered Nov 16 at 12:10









          Oleksandr

          7,77543467




          7,77543467
























              up vote
              9
              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
                9
                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
                  9
                  down vote










                  up vote
                  9
                  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 Nov 16 at 16:55


























                  community wiki





                  4 revs, 2 users 65%
                  glglgl























                      up vote
                      3
                      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
                        Nov 16 at 12:00















                      up vote
                      3
                      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
                        Nov 16 at 12:00













                      up vote
                      3
                      down vote










                      up vote
                      3
                      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 Nov 16 at 12:01

























                      answered Nov 16 at 11:59









                      Peter Lawrey

                      436k55550948




                      436k55550948








                      • 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
                        Nov 16 at 12:00














                      • 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
                        Nov 16 at 12:00








                      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
                      Nov 16 at 12:00




                      "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
                      Nov 16 at 12:00










                      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
                        Nov 16 at 12:01










                      • Its what he's using, but yeah... @ace , Integer.intValue();
                        – Joseph D
                        Nov 16 at 12:02















                      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
                        Nov 16 at 12:01










                      • Its what he's using, but yeah... @ace , Integer.intValue();
                        – Joseph D
                        Nov 16 at 12:02













                      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 Nov 16 at 12:00

























                      answered Nov 16 at 11:56









                      Joseph D

                      388110




                      388110












                      • I dislike Integer so would return int in this case. ;)
                        – Peter Lawrey
                        Nov 16 at 12:01










                      • Its what he's using, but yeah... @ace , Integer.intValue();
                        – Joseph D
                        Nov 16 at 12:02


















                      • I dislike Integer so would return int in this case. ;)
                        – Peter Lawrey
                        Nov 16 at 12:01










                      • Its what he's using, but yeah... @ace , Integer.intValue();
                        – Joseph D
                        Nov 16 at 12:02
















                      I dislike Integer so would return int in this case. ;)
                      – Peter Lawrey
                      Nov 16 at 12:01




                      I dislike Integer so would return int in this case. ;)
                      – Peter Lawrey
                      Nov 16 at 12:01












                      Its what he's using, but yeah... @ace , Integer.intValue();
                      – Joseph D
                      Nov 16 at 12:02




                      Its what he's using, but yeah... @ace , Integer.intValue();
                      – Joseph D
                      Nov 16 at 12:02


















                       

                      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

                      AnyDesk - Fatal Program Failure

                      How to calibrate 16:9 built-in touch-screen to a 4:3 resolution?

                      QoS: MAC-Priority for clients behind a repeater