How do I deal with null and duplicate values in a Java 8 Comparator?
up vote
12
down vote
favorite
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
add a comment |
up vote
12
down vote
favorite
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
1
Where should elements withpoNumber = null
go? After or before the elements with a non-null value in that field?
– Federico Peralta Schaffner
Nov 16 at 13:05
add a comment |
up vote
12
down vote
favorite
up vote
12
down vote
favorite
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
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
java java-8 comparator
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 withpoNumber = null
go? After or before the elements with a non-null value in that field?
– Federico Peralta Schaffner
Nov 16 at 13:05
add a comment |
1
Where should elements withpoNumber = 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
add a comment |
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));
add a comment |
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 Integer
s, and then adds a Comparator which naturally orders these Integer
s with the null
s 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.
add a comment |
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
4
"But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention ofcreated
being able to be null.
– glglgl
Nov 16 at 12:00
add a comment |
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
I dislikeInteger
so would returnint
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
add a comment |
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));
add a comment |
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));
add a comment |
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));
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));
edited Nov 16 at 20:47
answered Nov 16 at 12:10
Oleksandr
7,77543467
7,77543467
add a comment |
add a comment |
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 Integer
s, and then adds a Comparator which naturally orders these Integer
s with the null
s 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.
add a comment |
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 Integer
s, and then adds a Comparator which naturally orders these Integer
s with the null
s 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.
add a comment |
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 Integer
s, and then adds a Comparator which naturally orders these Integer
s with the null
s 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.
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 Integer
s, and then adds a Comparator which naturally orders these Integer
s with the null
s 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.
edited Nov 16 at 16:55
community wiki
4 revs, 2 users 65%
glglgl
add a comment |
add a comment |
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
4
"But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention ofcreated
being able to be null.
– glglgl
Nov 16 at 12:00
add a comment |
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
4
"But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention ofcreated
being able to be null.
– glglgl
Nov 16 at 12:00
add a comment |
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
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
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 ofcreated
being able to be null.
– glglgl
Nov 16 at 12:00
add a comment |
4
"But it throws NullPointerException whenever poNumber is null. If poNumber is not null then works fine." There is no mention ofcreated
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
add a comment |
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
I dislikeInteger
so would returnint
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
add a comment |
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
I dislikeInteger
so would returnint
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
add a comment |
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
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
edited Nov 16 at 12:00
answered Nov 16 at 11:56
Joseph D
388110
388110
I dislikeInteger
so would returnint
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
add a comment |
I dislikeInteger
so would returnint
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
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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