I have a simple object class:
public class Employee {
String name;
String secondName;
// Conctructor, getters & setters
}
List of employees:
List<Employee> employees = new ArrayList<>(Arrays.asList(
new Employee("Jake", "Bbb"),
new Employee("Ann", "Aaa"),
new Employee("Ivy", "Bbb"),
new Employee("Ivy", "Aaa"),
new Employee("Jake", "Aaa"),
new Employee("Tom", "Iii"),
new Employee("Neil", "Xxx"),
new Employee("Keith", "Ooo"),
new Employee("Tom", "Rrr")
));
I want to sort them in predefined order of secondNames first and than in natural order of names:
List<String> definedOrder = Arrays.asList("Iii", "Bbb", "Aaa");
in such way:
employees.sort(
Comparator.comparing((Employee e) -> definedOrder.indexOf(e.getSecondName()))
.thenComparing(Employee::getName));
for (Employee em : employees){
System.out.println(em.getSecondName() " / " em.getName());
}
And I experct to recive the predifined objects in the list first, then the rest objects:
Iii / Tom
Bbb / Ivy
Bbb / Jake
Aaa / Ann
Aaa / Ivy
Aaa / Jake
Ooo / Keith
Xxx / Neil
Rrr / Tom
But I receive objects firstly sorted in the natural order by names, (using thenComparing() method), and then from predefined comparison by secondNames:
Ooo / Keith
Xxx / Neil
Rrr / Tom
Iii / Tom
Bbb / Ivy
Bbb / Jake
Aaa / Ann
Aaa / Ivy
Aaa / Jake
CodePudding user response:
You're missing that definedOrder.indexOf(e.getSecondName())
returns -1
when second name is not found in definedOrder
.
That's why Ooo
, Xxx
and Rrr
appear before Iii
, Bbb
, and Aaa
.
And, as Ooo
, Xxx
and Rrr
all share the same value (-1
) for the purposes of comparing
, they are sorted by thenComparing(Employee::getName))
among themselves.
To fix this behavior, you can check if definedOrder.indexOf(e.getSecondName())
returns -1
and, if so, return Integer.MAX_VALUE
instead.