Reputation: 117
I have a little problem that is driving me crazy.
I have a
List<Integer>
with ids.List<ObjectA>
with 3 variables:
an id, and two stringI have to sort the second list by putting at the top the elements with id contained in the first list, then by string asc and by the second string asc.
What is the easiest way to make this work? I am trying to use the .sort(), Comparators etc.
An example:
@Getter
@Setter
public class ObjectA {
private Integer id;
private String code;
private String name;
}
// comparator:
static class SortByCode implements Comparator<ObjectA> {
public int compare(ObjectA a, ObjectA b) {
String as = a.getCode();
String bs = b.getCode();
return as.compareTo(bs);
}
}
static class SortByName implements Comparator<ObjectA> {
public int compare(ObjectA a, ObjectA b) {
String as = a.getName();
String bs = b.getName();
return as.compareTo(bs);
}
}
// then in service:
List<Integer> idsPreferred = new ArrayList<>();
List<ObjectA> listObj = new ArrayList<>();
idsPreferred = .... add preferred ids;
listObj = .... add objects;
listObj.sort(new SortByCode()).thenComparing(new SortByName());
With this i sort by code and by name - but i need to add the sorting by the first list - I need the elements that have an id contained in the List to come before the others.
Upvotes: 0
Views: 189
Reputation: 2202
I suppose something like this using chained comparing by extracted key:
listObj.sort(Comparator.comparing(o -> !idsPreferred.contains(((ObjectA) o).getId()))
.thenComparing(o -> ((ObjectA) o).getId())
.thenComparing(o -> ((ObjectA) o).getCode())
.thenComparing(o -> ((ObjectA) o).getName()));
or
listObj.sort(Comparator.comparing(ObjectA::getId,
(id1,id2)-> {if (!((idsPreferred.contains(id1))^idsPreferred.contains(id2)))
return 0;
else return (idsPreferred.contains(id2))?1:-1;})
.thenComparing(ObjectA::getId)
.thenComparing(ObjectA::getCode)
.thenComparing(ObjectA::getName));
Upvotes: 4
Reputation: 1146
The solution will involve 2 steps-
Upvotes: -1