Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java8流中的条件排序_Java_Sorting_Generics_Lambda_Java Stream - Fatal编程技术网

Java8流中的条件排序

Java8流中的条件排序,java,sorting,generics,lambda,java-stream,Java,Sorting,Generics,Lambda,Java Stream,我试图根据买入或卖出方向对股票订单列表进行排序 我试过这样的方法: orders.stream() .sorted(o -> "BUY".equals(o.side) ? comparing(Order::getPrice) : comparing(Order::getPrice).reversed()); 我看到下面的错误信息,我不清楚 不兼容的类型。必需的int,但已向Comparator推断

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

我试过这样的方法:

orders.stream()
      .sorted(o -> "BUY".equals(o.side) ? 
              comparing(Order::getPrice) : 
              comparing(Order::getPrice).reversed());
我看到下面的错误信息,我不清楚

不兼容的类型。必需的int,但已向Comparator推断“comparing”:不存在类型变量T,U的实例,因此Comparator符合Integer


我有另一个想法:如何根据类型对流进行分区,然后在后期修复排序顺序

Map<Boolean, List<Order>> filtered = orders.stream()
                   .sorted(Order::getPrice)
                   .collect(Collectors.partitioningBy(o -> "BUY".equals(o.side)));
// #partitioningBy guarantees true/false will be in the map
List<Order> bought = filtered.get(true);
List<Order> sold = filtered.get(false);
Collections.reverse(sold); //since you want sold backwards
Map filtered=orders.stream()
.sorted(订单::getPrice)
.collect(collector.partitionby(o->“BUY.”等于(o.side));
//#Partitioning By保证真/假将出现在地图上
List bunded=filtered.get(true);
列表已售出=已筛选。获取(false);
收款。反向(已售出)//既然你想倒卖
缺点是对于大订单(成百上千的商品),这可能会很慢,因为您同时进行买卖(而不是两个较小的种类)。您可以将排序移到下游收集器(甚至是收集的对象)中,但它需要更多的代码:

Map<Boolean, List<Order>> filtered = orders.stream()
                   .collect(Collectors.partitioningBy(o -> "BUY".equals(o.side)));
List<Order> bought = filtered.get(true);
List<Order> sold = filtered.get(false);
bought.sort(Comparator.comparingInt(Order::getPrice));
sold.sort(Comparator.comparingInt(Order::getPrice).reversed());
Map filtered=orders.stream()
.collect(collector.partitionby(o->“BUY.”等于(o.side));
List bunded=filtered.get(true);
列表已售出=已筛选。获取(false);
bunded.sort(Comparator.comparingit(Order::getPrice));
sell.sort(Comparator.comparingit(Order::getPrice.reversed());
对于较小的输入,第一个是可以接受的。最重要的是,它消除了(有些)混乱的lambda,消除了三元/lambda混合

编辑:

如果您只对其中一个结果感兴趣,那么不需要将逻辑放在同一个流中:

//To fetch the items that were not "BUY"
List<Order> sold = orders.stream()
                .filter(o -> !"BUY".equals(o.side))
                .sorted(Comparator.comparingInt(Order::getPrice).reversed())
                .collect(Collectors.toList());

//or if you're looking for the sold items at this point in code
List<Order> bought = orders.stream()
                .filter(o -> "BUY".equals(o.side))
                .sorted(Comparator.comparingInt(Order::getPrice))
                .collect(Collectors.toList());
//获取不是“购买”的项目
List Seld=orders.stream()
.过滤器(o->!“购买”。等于(o侧))
.sorted(Comparator.comparingInt(Order::getPrice).reversed())
.collect(Collectors.toList());
//或者,如果您正在代码中查找此时已售出的项目
List bunded=orders.stream()
.filter(o->“购买”。等于(o.side))
.sorted(Comparator.comparingInt(Order::getPrice))
.collect(Collectors.toList());

我有另一个想法:如何根据类型对流进行分区,然后对排序顺序进行后期修复

Map<Boolean, List<Order>> filtered = orders.stream()
                   .sorted(Order::getPrice)
                   .collect(Collectors.partitioningBy(o -> "BUY".equals(o.side)));
// #partitioningBy guarantees true/false will be in the map
List<Order> bought = filtered.get(true);
List<Order> sold = filtered.get(false);
Collections.reverse(sold); //since you want sold backwards
Map filtered=orders.stream()
.sorted(订单::getPrice)
.collect(collector.partitionby(o->“BUY.”等于(o.side));
//#Partitioning By保证真/假将出现在地图上
List bunded=filtered.get(true);
列表已售出=已筛选。获取(false);
收款。反向(已售出)//既然你想倒卖
缺点是对于大订单(成百上千的商品),这可能会很慢,因为您同时进行买卖(而不是两个较小的种类)。您可以将排序移到下游收集器(甚至是收集的对象)中,但它需要更多的代码:

Map<Boolean, List<Order>> filtered = orders.stream()
                   .collect(Collectors.partitioningBy(o -> "BUY".equals(o.side)));
List<Order> bought = filtered.get(true);
List<Order> sold = filtered.get(false);
bought.sort(Comparator.comparingInt(Order::getPrice));
sold.sort(Comparator.comparingInt(Order::getPrice).reversed());
Map filtered=orders.stream()
.collect(collector.partitionby(o->“BUY.”等于(o.side));
List bunded=filtered.get(true);
列表已售出=已筛选。获取(false);
bunded.sort(Comparator.comparingit(Order::getPrice));
sell.sort(Comparator.comparingit(Order::getPrice.reversed());
对于较小的输入,第一个是可以接受的。最重要的是,它消除了(有些)混乱的lambda,消除了三元/lambda混合

编辑:

如果您只对其中一个结果感兴趣,那么不需要将逻辑放在同一个流中:

//To fetch the items that were not "BUY"
List<Order> sold = orders.stream()
                .filter(o -> !"BUY".equals(o.side))
                .sorted(Comparator.comparingInt(Order::getPrice).reversed())
                .collect(Collectors.toList());

//or if you're looking for the sold items at this point in code
List<Order> bought = orders.stream()
                .filter(o -> "BUY".equals(o.side))
                .sorted(Comparator.comparingInt(Order::getPrice))
                .collect(Collectors.toList());
//获取不是“购买”的项目
List Seld=orders.stream()
.过滤器(o->!“购买”。等于(o侧))
.sorted(Comparator.comparingInt(Order::getPrice).reversed())
.collect(Collectors.toList());
//或者,如果您正在代码中查找此时已售出的项目
List bunded=orders.stream()
.filter(o->“购买”。等于(o.side))
.sorted(Comparator.comparingInt(Order::getPrice))
.collect(Collectors.toList());

您可能希望使用由
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::sort
    方法,但是
  • 流本身没有终止,因此管道永远不会执行。这样的终端操作是
    收集
    减少
    查找第一个

  • …如果我只使用排序(比较(Order::getPrice))而不是三元操作,为什么它不抱怨呢

    因为
    sorted
    方法需要
    Comparator
    ,但是您的lambda表达式与此不兼容

    首先,lambda表达式以
    o->…
    开头,只要
    Comparator
    中的方法是
    int compare(to1,t2)
    就不正确,因此lambda表达式应该类似于
    (o1,o2)

    其次,返回类型必须是
    int
    (因为
    int比较(to1,t2)
    )。仅使用
    比较(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());
    
    //这是lambda表达式
    双功能双功能=(l,r)->
    “买”等于(左面)和“买”等于(右面)?
    Comparator.comparing(订单::getPrice):
    Comparator.comparing(Order::getPrice).reversed();
    List sortedOrders=orders.stream()
    .sorted((l,r)->biFunction.apply(l,r).compare(l,r))
    .collect(Collectors.toList());
    

    这显然不是比较器,但可以使用。整个过程可以简化为我上面描述的解决方案。

    您可能需要使用这个
    比较器
    ,通过
    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);
        };
    }
    

    BUY 3 BUY 4 SELL 9 BUY 5 SELL 6 BUY 7 SELL 2 SELL 1 BUY 8

    // We define a comparator here which returns ascending order if the side is BUY,
    // or descending if it is SELL.
    final Comparator<Order> comparator = (left, right) -> {
        Comparator<Order> c = Comparator.comparing(Order::getPrice);
        if (Objects.equals(left.getSide(), "SELL")) {
            c = c.reversed();
        }
        return c.compare(left, right);
    };
    
    // We stream over the orders, and partition them by their side. We sort the
    // resulting lists by their own comparison method.
    Map<String, List<Order>> map = orders.stream()
        .collect(Collectors.groupingBy(Order::getSide, toSortedList(comparator)));
    Iterator<Order> buyIt = map.get("BUY").iterator();
    Iterator<Order> sellIt = map.get("SELL").iterator();
    
    // At last, we stream again over the elements, consuming from both iterators
    // based on the value of 'side'
    orders.stream()
        .map(order -> Objects.equals(order.getSide(), "BUY") ? buyIt.next() : sellIt.next())
        .forEach(System.out::println);
    
    // Almost the same as Collectors.toList(), but sorts the list by the provided
    // comparator.
    public static <T> Collector<T, List<T>, List<T>> toSortedList(Comparator<T> comparator) {
        return Collector.of(
            ArrayList::new,
            List::add,
            (left, right) -> {
                left.addAll(right); return left;
            },
            list -> list.stream()
                .sorted(comparator)
                .collect(Collectors.toList())
        );
    }