像开关条件一样排序Java Stream

Ant*_*682 4 java collections functional-programming java-8 java-stream

我正在尝试通过其中一个字段按特定顺序对流进行排序.

现在我通过将流转换为列表并使用开关然后将它们重新加入到所需顺序的列表中来实现此目的.


    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);

我想知道是否有任何改变使用流排序方法和使用自定义比较器或类似的东西来实现这一点.

提前致谢.

Hol*_*ger 6

您可以使用明确的顺序创建比较器

List<String> order = Arrays.asList("Orange", "Apple", "WaterMelon");
Comparator<String> comp
    = Comparator.comparingInt(name -> order.indexOf(name)-Integer.MIN_VALUE);
Run Code Online (Sandbox Code Playgroud)

可以使用像

List<Fruit> genericFruitList = fruits
    .sorted(Comparator.comparing(fruit -> fruit.getName(), comp))
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

但是,对整个列表进行排序,尤其是使用List.indexOf基于比较器的列表,可能会非常低效.另一种选择

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());
Run Code Online (Sandbox Code Playgroud)

Fruit它只执行哈希查找,并且只对不同的映射进行排序.

这可以看作是Bucket Sort的变种.


And*_*ner 5

如果你想将水果分类成特定的顺序(首先是橙子,然后是苹果,然后是西瓜,然后是"其他"),你可以定义一个比较器:

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();
});
Run Code Online (Sandbox Code Playgroud)

然后排序:

List<Fruit> genericFruitList = fruits.stream().sorted(comparator).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)