首页 > 解决方案 > Java8 流中的条件排序

问题描述

我正在尝试根据买入或卖出方向对股票订单列表进行排序。

我试过类似的东西:

orders.stream()
      .sorted(o -> "BUY".equals(o.side) ? 
              comparing(Order::getPrice) : 
              comparing(Order::getPrice).reversed());

我在下面看到下面的错误消息,我不清楚。

不兼容的类型。必需的 int 但“比较”被推断为 Comparator:不存在类型变量 T、U 的实例,因此 Comparator 符合 Integer。

标签: javasortinggenericslambdajava-stream

解决方案


你可能想使用这个由参数Comparator<Order>调整的。o.side

static Comparator<Order> buyComparator() {
    return (l, r) -> {
        Comparator<Order> comparator = Comparator.comparing(Order::getPrice);
        comparator = "BUY".equals(l.side) && "BUY".equals(r.side) ?
                comparator : comparator.reversed();
        return comparator.compare(l ,r);
    };
}

那么使用就相当简单了,你可以通过 Stream API 返回一个新的排序列表或者改变原来的排序列表:

  1. 流API:
List<Order> sortedOrders = orders.stream()
         .sorted(buyComparator())
         .collect(Collectors.toList());
  1. 使用Collections.sort(List, Comparator)
Collections.sort(orders, buyComparator());

顺便说一句,您的代码中有两个错误:

  1. 没有Stream::sort办法,但是Stream::sorted
  2. Stream 本身没有终止,因此管道永远不会执行。这样的终端操作是collect, reduce,findFirst等等...

...如果我只使用 sorted(comparing(Order::getPrice)) 而不是三元运算,为什么它不会抱怨?

因为该sorted方法期望Comparator<Order>但您的 lambda 表达式不符合该要求。

首先,您的 lambda 表达式以o -> ...which 不正确开头,只要方法 inComparator因此int compare(T o1, T o2)lambda 表达式应该看起来像(o1, o2).

其次,返回类型必须是int(因为int compare(T o1, T o2))。仅使用comparing(Order::getPrice)是好的,但只要您选择 lambda 表达式而不是方法引用,那么返回类型就很清楚了:

// this is your lambda expression
BiFunction<Order, Order, Comparator<Order>> biFunction = (l, r) -> 
    "BUY".equals(l.side) && "BUY".equals(r.side) ?
            Comparator.comparing(Order::getPrice) :
            Comparator.comparing(Order::getPrice).reversed();

List<Order> sortedOrders = orders.stream()
            .sorted((l, r) -> biFunction.apply(l, r).compare(l ,r))
            .collect(Collectors.toList());

这显然不是Comparator<Order>,但可以使用。整个事情可以简化为我上面描述的解决方案。


推荐阅读