Reputation: 2759
I need a way in Java 8 to sort a list of Item objects using on multiple Comparator objects.
The application creates a Comparator on every user action. It's stores the Comparator objects in an ArrayList. It is possible to sort on one Comparator Item but now we need a way to make it possible to sort on multiple Comarator items at the same time.
This line of code I use to sort the list:
tbl.getItems().stream().sorted(groupingComparator);
The variable groupingComparator is from type Comparator<Item>
Now I need to sort on multiple fields that are stored in
ArrayList<Comparator<Item>>
Is this possible in Java 8? And how can I implement this?
Upvotes: 3
Views: 680
Reputation: 6200
You can use the thenComparing(Comparator)
method available from the Comparator interface to chain multiple Comparators together. See the example below, to create such a chained Comparator from a List using streams.
The domain class we want to use for sorting:
public static class Order {
String customer;
String item;
public Order(String customer, String item)
{
this.customer = customer;
this.item = item;
}
public String toString() {
return "Customer: " + customer + " Item: " + item;
}
}
Sample code:
public static void main(String... args) throws Throwable
{
List<Order> orders = new ArrayList<>();
orders.add(new Order("A", "Item 1"));
orders.add(new Order("B", "Item 3"));
orders.add(new Order("A", "Item 2"));
orders.add(new Order("B", "Item 1"));
List<Comparator<Order>> comparators =
Arrays.asList((o1, o2) -> o1.customer.compareTo(o2.customer), // comparator for customer names
(o1, o2) -> o1.item.compareTo(o2.item)); // comparator for item names
Comparator<Order> comp =
comparators.stream()
.reduce(Comparator::thenComparing)
// use a default comparator if the comparator list was empty
.orElse(Comparator.comparing(Object::toString));
orders.stream().sorted(comp).forEach((order) -> System.out.println(order));
}
This snippet will print the Orders sorted first by Customer then by Item name.
Upvotes: 5
Reputation: 691953
As simple as that:
public class CompositeComparator implements Comparator<Item> {
private List<Comparator<Item>> comparators;
public CompositeComparator(List<Comparator<Item>> comparators) {
this.comparators = comparators;
}
@Override
public int compare(Item o1, Item o2) {
int result = 0;
for (Comparator<Item> c : comparators) {
result = c.compare(o1, o2);
if (result != 0) {
break;
}
}
return result;
}
}
Upvotes: 2