Sort with one element at the end
I have a list of objects and I want to sort it alphabetically by an attribute. But I want to add an exception rule if this attribute matches a specific string. For example:
public class Car {
String name;
}
List<Car> cars = asList(
new Car("Unassigned"),
new Car("Nissan"),
new Car("Yamaha"),
new Car("Honda"));
List<Car> sortedCars = cars
.stream
.sorted(Comparator.comparing(Car::getName))
.collect(Collectors.toList());
If cars.name == "Unassigned"
then this car should remain at the end of the list and the result would be:
[Car<Honda>, Car<Nissan>, Car<Yamaha>, Car<Unassigned>]
java sorting java-8 java-stream
add a comment |
I have a list of objects and I want to sort it alphabetically by an attribute. But I want to add an exception rule if this attribute matches a specific string. For example:
public class Car {
String name;
}
List<Car> cars = asList(
new Car("Unassigned"),
new Car("Nissan"),
new Car("Yamaha"),
new Car("Honda"));
List<Car> sortedCars = cars
.stream
.sorted(Comparator.comparing(Car::getName))
.collect(Collectors.toList());
If cars.name == "Unassigned"
then this car should remain at the end of the list and the result would be:
[Car<Honda>, Car<Nissan>, Car<Yamaha>, Car<Unassigned>]
java sorting java-8 java-stream
add a comment |
I have a list of objects and I want to sort it alphabetically by an attribute. But I want to add an exception rule if this attribute matches a specific string. For example:
public class Car {
String name;
}
List<Car> cars = asList(
new Car("Unassigned"),
new Car("Nissan"),
new Car("Yamaha"),
new Car("Honda"));
List<Car> sortedCars = cars
.stream
.sorted(Comparator.comparing(Car::getName))
.collect(Collectors.toList());
If cars.name == "Unassigned"
then this car should remain at the end of the list and the result would be:
[Car<Honda>, Car<Nissan>, Car<Yamaha>, Car<Unassigned>]
java sorting java-8 java-stream
I have a list of objects and I want to sort it alphabetically by an attribute. But I want to add an exception rule if this attribute matches a specific string. For example:
public class Car {
String name;
}
List<Car> cars = asList(
new Car("Unassigned"),
new Car("Nissan"),
new Car("Yamaha"),
new Car("Honda"));
List<Car> sortedCars = cars
.stream
.sorted(Comparator.comparing(Car::getName))
.collect(Collectors.toList());
If cars.name == "Unassigned"
then this car should remain at the end of the list and the result would be:
[Car<Honda>, Car<Nissan>, Car<Yamaha>, Car<Unassigned>]
java sorting java-8 java-stream
java sorting java-8 java-stream
edited 14 hours ago
Lii
7,14344162
7,14344162
asked 15 hours ago
bpereirabpereira
396316
396316
add a comment |
add a comment |
5 Answers
5
active
oldest
votes
List<Car> sortedCars = cars
.stream()
.sorted(Comparator.comparing(
Car::getName,
Comparator.comparing((String x) -> x.equals("Unassigned"))
.thenComparing(Comparator.naturalOrder())))
.collect(Collectors.toList());
There are a lot of things going on here. First I am using Comparator.comparing(Function, Comparator)
; then (String x) -> x.equals("Unassigned")
which actually compares a Boolean
(that is Comparable
); then the fact that (String x)
is used - as this type witness is used to correctly infer the types...
1
Clever! But I think that the trick withcomparing((String x) -> x.equals("Unassigned"))
is so tricky that it warrants an explanatory comment in the code, it it where to be used in production...
– Lii
14 hours ago
1
@Lii which is left as an exercise to the reader... I mentioned it sorts aBoolean
(that isComparable
), that should provide the proper direction.
– Eugene
14 hours ago
add a comment |
The most direct and and easy-to-read solution is probably to write a custom comparator that implements your sorting logic.
You can still use the Comparator.comparing
method to make it a bit prittier, though:
public static final String UNASSIGNED = "Unassigned";
List<Car> cars = List.of(
new Car("Unassigned"),
new Car("Nissan"),
new Car("Yamaha"),
new Car("Honda"));
List<Car> sortedCars = cars.stream()
.sorted(Comparator.comparing(Car::getName, (name1, name2) -> {
if (name1.equals(name2)) return 0;
if (name1.equals(UNASSIGNED)) return 1;
if (name2.equals(UNASSIGNED)) return -1;
return name1.compareTo(name2);
}))
.collect(Collectors.toList());
Also, it's good style to use a named constant for special values like your "Unassigned"
.
add a comment |
You could just replace "Unassigned" with an end-of-alphabet string in your comparator.
Comparator.comparing(car -> car.getName().equals("Unassigned") ? "ZZZ" : car.getName())
add a comment |
Alternatively, just remove all instances of "Unassigned" and add however many to the end of the List
after. For example:
int numberOfUnassigned = 0;
for (Iterator<Car> iterator = sortedCars.iterator(); iterator.hasNext();) {
String str = iterator.next().getName();
if (str.equals("Unassigned")) {
iterator.remove();
numberOfUnassigned++;
}
}
And then add the number of numberOfUnassigned
to the end.
add a comment |
One way to possibly do that would be using partitioning as:
Map<Boolean, List<Car>> partitionedCars = cars
.stream()
.collect(Collectors.partitioningBy(a -> a.getName().equals("Unassigned")));
List<Car> sortedCars = Stream.concat(partitionedCars.get(Boolean.FALSE).stream()
.sorted(Comparator.comparing(Car::getName)), partitionedCars.get(Boolean.TRUE).stream())
.collect(Collectors.toList());
3
this is ingenious, but wasteful or resources... of course.
– Eugene
14 hours ago
add a comment |
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
});
}
});
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%2f55102884%2fsort-with-one-element-at-the-end%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
List<Car> sortedCars = cars
.stream()
.sorted(Comparator.comparing(
Car::getName,
Comparator.comparing((String x) -> x.equals("Unassigned"))
.thenComparing(Comparator.naturalOrder())))
.collect(Collectors.toList());
There are a lot of things going on here. First I am using Comparator.comparing(Function, Comparator)
; then (String x) -> x.equals("Unassigned")
which actually compares a Boolean
(that is Comparable
); then the fact that (String x)
is used - as this type witness is used to correctly infer the types...
1
Clever! But I think that the trick withcomparing((String x) -> x.equals("Unassigned"))
is so tricky that it warrants an explanatory comment in the code, it it where to be used in production...
– Lii
14 hours ago
1
@Lii which is left as an exercise to the reader... I mentioned it sorts aBoolean
(that isComparable
), that should provide the proper direction.
– Eugene
14 hours ago
add a comment |
List<Car> sortedCars = cars
.stream()
.sorted(Comparator.comparing(
Car::getName,
Comparator.comparing((String x) -> x.equals("Unassigned"))
.thenComparing(Comparator.naturalOrder())))
.collect(Collectors.toList());
There are a lot of things going on here. First I am using Comparator.comparing(Function, Comparator)
; then (String x) -> x.equals("Unassigned")
which actually compares a Boolean
(that is Comparable
); then the fact that (String x)
is used - as this type witness is used to correctly infer the types...
1
Clever! But I think that the trick withcomparing((String x) -> x.equals("Unassigned"))
is so tricky that it warrants an explanatory comment in the code, it it where to be used in production...
– Lii
14 hours ago
1
@Lii which is left as an exercise to the reader... I mentioned it sorts aBoolean
(that isComparable
), that should provide the proper direction.
– Eugene
14 hours ago
add a comment |
List<Car> sortedCars = cars
.stream()
.sorted(Comparator.comparing(
Car::getName,
Comparator.comparing((String x) -> x.equals("Unassigned"))
.thenComparing(Comparator.naturalOrder())))
.collect(Collectors.toList());
There are a lot of things going on here. First I am using Comparator.comparing(Function, Comparator)
; then (String x) -> x.equals("Unassigned")
which actually compares a Boolean
(that is Comparable
); then the fact that (String x)
is used - as this type witness is used to correctly infer the types...
List<Car> sortedCars = cars
.stream()
.sorted(Comparator.comparing(
Car::getName,
Comparator.comparing((String x) -> x.equals("Unassigned"))
.thenComparing(Comparator.naturalOrder())))
.collect(Collectors.toList());
There are a lot of things going on here. First I am using Comparator.comparing(Function, Comparator)
; then (String x) -> x.equals("Unassigned")
which actually compares a Boolean
(that is Comparable
); then the fact that (String x)
is used - as this type witness is used to correctly infer the types...
edited 14 hours ago
answered 15 hours ago
EugeneEugene
71.1k9102170
71.1k9102170
1
Clever! But I think that the trick withcomparing((String x) -> x.equals("Unassigned"))
is so tricky that it warrants an explanatory comment in the code, it it where to be used in production...
– Lii
14 hours ago
1
@Lii which is left as an exercise to the reader... I mentioned it sorts aBoolean
(that isComparable
), that should provide the proper direction.
– Eugene
14 hours ago
add a comment |
1
Clever! But I think that the trick withcomparing((String x) -> x.equals("Unassigned"))
is so tricky that it warrants an explanatory comment in the code, it it where to be used in production...
– Lii
14 hours ago
1
@Lii which is left as an exercise to the reader... I mentioned it sorts aBoolean
(that isComparable
), that should provide the proper direction.
– Eugene
14 hours ago
1
1
Clever! But I think that the trick with
comparing((String x) -> x.equals("Unassigned"))
is so tricky that it warrants an explanatory comment in the code, it it where to be used in production...– Lii
14 hours ago
Clever! But I think that the trick with
comparing((String x) -> x.equals("Unassigned"))
is so tricky that it warrants an explanatory comment in the code, it it where to be used in production...– Lii
14 hours ago
1
1
@Lii which is left as an exercise to the reader... I mentioned it sorts a
Boolean
(that is Comparable
), that should provide the proper direction.– Eugene
14 hours ago
@Lii which is left as an exercise to the reader... I mentioned it sorts a
Boolean
(that is Comparable
), that should provide the proper direction.– Eugene
14 hours ago
add a comment |
The most direct and and easy-to-read solution is probably to write a custom comparator that implements your sorting logic.
You can still use the Comparator.comparing
method to make it a bit prittier, though:
public static final String UNASSIGNED = "Unassigned";
List<Car> cars = List.of(
new Car("Unassigned"),
new Car("Nissan"),
new Car("Yamaha"),
new Car("Honda"));
List<Car> sortedCars = cars.stream()
.sorted(Comparator.comparing(Car::getName, (name1, name2) -> {
if (name1.equals(name2)) return 0;
if (name1.equals(UNASSIGNED)) return 1;
if (name2.equals(UNASSIGNED)) return -1;
return name1.compareTo(name2);
}))
.collect(Collectors.toList());
Also, it's good style to use a named constant for special values like your "Unassigned"
.
add a comment |
The most direct and and easy-to-read solution is probably to write a custom comparator that implements your sorting logic.
You can still use the Comparator.comparing
method to make it a bit prittier, though:
public static final String UNASSIGNED = "Unassigned";
List<Car> cars = List.of(
new Car("Unassigned"),
new Car("Nissan"),
new Car("Yamaha"),
new Car("Honda"));
List<Car> sortedCars = cars.stream()
.sorted(Comparator.comparing(Car::getName, (name1, name2) -> {
if (name1.equals(name2)) return 0;
if (name1.equals(UNASSIGNED)) return 1;
if (name2.equals(UNASSIGNED)) return -1;
return name1.compareTo(name2);
}))
.collect(Collectors.toList());
Also, it's good style to use a named constant for special values like your "Unassigned"
.
add a comment |
The most direct and and easy-to-read solution is probably to write a custom comparator that implements your sorting logic.
You can still use the Comparator.comparing
method to make it a bit prittier, though:
public static final String UNASSIGNED = "Unassigned";
List<Car> cars = List.of(
new Car("Unassigned"),
new Car("Nissan"),
new Car("Yamaha"),
new Car("Honda"));
List<Car> sortedCars = cars.stream()
.sorted(Comparator.comparing(Car::getName, (name1, name2) -> {
if (name1.equals(name2)) return 0;
if (name1.equals(UNASSIGNED)) return 1;
if (name2.equals(UNASSIGNED)) return -1;
return name1.compareTo(name2);
}))
.collect(Collectors.toList());
Also, it's good style to use a named constant for special values like your "Unassigned"
.
The most direct and and easy-to-read solution is probably to write a custom comparator that implements your sorting logic.
You can still use the Comparator.comparing
method to make it a bit prittier, though:
public static final String UNASSIGNED = "Unassigned";
List<Car> cars = List.of(
new Car("Unassigned"),
new Car("Nissan"),
new Car("Yamaha"),
new Car("Honda"));
List<Car> sortedCars = cars.stream()
.sorted(Comparator.comparing(Car::getName, (name1, name2) -> {
if (name1.equals(name2)) return 0;
if (name1.equals(UNASSIGNED)) return 1;
if (name2.equals(UNASSIGNED)) return -1;
return name1.compareTo(name2);
}))
.collect(Collectors.toList());
Also, it's good style to use a named constant for special values like your "Unassigned"
.
edited 9 hours ago
answered 14 hours ago
LiiLii
7,14344162
7,14344162
add a comment |
add a comment |
You could just replace "Unassigned" with an end-of-alphabet string in your comparator.
Comparator.comparing(car -> car.getName().equals("Unassigned") ? "ZZZ" : car.getName())
add a comment |
You could just replace "Unassigned" with an end-of-alphabet string in your comparator.
Comparator.comparing(car -> car.getName().equals("Unassigned") ? "ZZZ" : car.getName())
add a comment |
You could just replace "Unassigned" with an end-of-alphabet string in your comparator.
Comparator.comparing(car -> car.getName().equals("Unassigned") ? "ZZZ" : car.getName())
You could just replace "Unassigned" with an end-of-alphabet string in your comparator.
Comparator.comparing(car -> car.getName().equals("Unassigned") ? "ZZZ" : car.getName())
answered 15 hours ago
MikeFHayMikeFHay
3,18532035
3,18532035
add a comment |
add a comment |
Alternatively, just remove all instances of "Unassigned" and add however many to the end of the List
after. For example:
int numberOfUnassigned = 0;
for (Iterator<Car> iterator = sortedCars.iterator(); iterator.hasNext();) {
String str = iterator.next().getName();
if (str.equals("Unassigned")) {
iterator.remove();
numberOfUnassigned++;
}
}
And then add the number of numberOfUnassigned
to the end.
add a comment |
Alternatively, just remove all instances of "Unassigned" and add however many to the end of the List
after. For example:
int numberOfUnassigned = 0;
for (Iterator<Car> iterator = sortedCars.iterator(); iterator.hasNext();) {
String str = iterator.next().getName();
if (str.equals("Unassigned")) {
iterator.remove();
numberOfUnassigned++;
}
}
And then add the number of numberOfUnassigned
to the end.
add a comment |
Alternatively, just remove all instances of "Unassigned" and add however many to the end of the List
after. For example:
int numberOfUnassigned = 0;
for (Iterator<Car> iterator = sortedCars.iterator(); iterator.hasNext();) {
String str = iterator.next().getName();
if (str.equals("Unassigned")) {
iterator.remove();
numberOfUnassigned++;
}
}
And then add the number of numberOfUnassigned
to the end.
Alternatively, just remove all instances of "Unassigned" and add however many to the end of the List
after. For example:
int numberOfUnassigned = 0;
for (Iterator<Car> iterator = sortedCars.iterator(); iterator.hasNext();) {
String str = iterator.next().getName();
if (str.equals("Unassigned")) {
iterator.remove();
numberOfUnassigned++;
}
}
And then add the number of numberOfUnassigned
to the end.
answered 14 hours ago
achAmháinachAmháin
3,1923832
3,1923832
add a comment |
add a comment |
One way to possibly do that would be using partitioning as:
Map<Boolean, List<Car>> partitionedCars = cars
.stream()
.collect(Collectors.partitioningBy(a -> a.getName().equals("Unassigned")));
List<Car> sortedCars = Stream.concat(partitionedCars.get(Boolean.FALSE).stream()
.sorted(Comparator.comparing(Car::getName)), partitionedCars.get(Boolean.TRUE).stream())
.collect(Collectors.toList());
3
this is ingenious, but wasteful or resources... of course.
– Eugene
14 hours ago
add a comment |
One way to possibly do that would be using partitioning as:
Map<Boolean, List<Car>> partitionedCars = cars
.stream()
.collect(Collectors.partitioningBy(a -> a.getName().equals("Unassigned")));
List<Car> sortedCars = Stream.concat(partitionedCars.get(Boolean.FALSE).stream()
.sorted(Comparator.comparing(Car::getName)), partitionedCars.get(Boolean.TRUE).stream())
.collect(Collectors.toList());
3
this is ingenious, but wasteful or resources... of course.
– Eugene
14 hours ago
add a comment |
One way to possibly do that would be using partitioning as:
Map<Boolean, List<Car>> partitionedCars = cars
.stream()
.collect(Collectors.partitioningBy(a -> a.getName().equals("Unassigned")));
List<Car> sortedCars = Stream.concat(partitionedCars.get(Boolean.FALSE).stream()
.sorted(Comparator.comparing(Car::getName)), partitionedCars.get(Boolean.TRUE).stream())
.collect(Collectors.toList());
One way to possibly do that would be using partitioning as:
Map<Boolean, List<Car>> partitionedCars = cars
.stream()
.collect(Collectors.partitioningBy(a -> a.getName().equals("Unassigned")));
List<Car> sortedCars = Stream.concat(partitionedCars.get(Boolean.FALSE).stream()
.sorted(Comparator.comparing(Car::getName)), partitionedCars.get(Boolean.TRUE).stream())
.collect(Collectors.toList());
edited 4 hours ago
answered 15 hours ago
NamanNaman
44.1k11102203
44.1k11102203
3
this is ingenious, but wasteful or resources... of course.
– Eugene
14 hours ago
add a comment |
3
this is ingenious, but wasteful or resources... of course.
– Eugene
14 hours ago
3
3
this is ingenious, but wasteful or resources... of course.
– Eugene
14 hours ago
this is ingenious, but wasteful or resources... of course.
– Eugene
14 hours ago
add a comment |
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.
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%2f55102884%2fsort-with-one-element-at-the-end%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