I'm trying to sort a stream by an specific order by one of its fields.
Now I'm achieving this by converting streams to list and using a switch and then rejoining them into a list in the desired order.
fruits.forEach(fruit -> { switch (fruit.getName()) { case "Orange": orangesList.add(fruit); break; case "Apple": applesList.add(fruit); break; case "WaterMelon": watermelonList.add(fruit); break; default: otherFruits.add(fruit); break; } }); genericFruitList.addAll(0, orangeList); genericFruitList.addAll(1, applesList); genericFruitList.addAll(2, watermelonList); genericFruitList.addAll(3, otherFruits);
I wonder if there's any change to achieve this using stream sorted method and using a custom comparator or something like that.
Thanks in advance.
You can create a comparator using an explicit order like
List<String> order = Arrays.asList("Orange", "Apple", "WaterMelon");
Comparator<String> comp
= Comparator.comparingInt(name -> order.indexOf(name)-Integer.MIN_VALUE);
which can be used like
List<Fruit> genericFruitList = fruits
.sorted(Comparator.comparing(fruit -> fruit.getName(), comp))
.collect(Collectors.toList());
however, sorting the entire list, especially with an List.indexOf
based comparator, can be quiet inefficient. An alternative would be
List<Fruit> genericFruitList = fruits
.collect(Collectors.groupingBy(fruit -> fruit.getName()))
.entrySet().stream()
.sorted(Map.Entry.comparingByKey(comp))
.flatMap(e -> e.getValue().stream())
.collect(Collectors.toList());
which just performs a hash lookup per Fruit
and only sort the distinct mappings.
This can be seen as a variant of Bucket Sort .
If you want to sort the fruit into a particular order (oranges first, then apples, then watermelon, then "other"), you could define a comparator thus:
List<String> order = Arrays.asList("Orange", "Apple", "Watermelon");
Comparator<Fruit> comparator = Comparator.comparing(f -> {
int i = order.indexOf(f.getName());
return (i >= 0) ? i : order.size();
});
and then sort:
List<Fruit> genericFruitList = fruits.stream().sorted(comparator).collect(Collectors.toList());
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.