如何使用 Java 流 API 对列表中的项目进行分组和计数

问题描述 投票:0回答:4

我有以下

OrderItems
课程:

public class OrderItems {
    public int id;
    public double portion;
}

以及以下

List<OrderItems>

List<OrderItems> orderItems = new ArrayList<>();
orderItems.add(new OrderItems(1,0.5));
orderItems.add(new OrderItems(2,1));
orderItems.add(new OrderItems(1,0.5));
orderItems.add(new OrderItems(1,1.5));
orderItems.add(new OrderItems(2,1));
orderItems.add(new OrderItems(2,0.5));

如何将此列表分组并使用流 API 转换为以下

NewOrderItems
类?

public class NewOrderItems {
   public int id;
   public double portion;
   public long amount;
}

结果应该是这样的:

NewOrderItems{id=1, portion=0.5, amount=2}
NewOrderItems{id=1, portion=1.5, amount=1}
NewOrderItems{id=2, portion=0.5, amount=1}
NewOrderItems{id=2, portion=1.0, amount=2}
java list java-stream group
4个回答
1
投票

我们可以利用

public class GroupItem {
    public static void main(String[] args) {
        List<OrderItems> orderItems = new ArrayList<>();
        orderItems.add(new OrderItems(1, 0.5));
        orderItems.add(new OrderItems(2, 1));
        orderItems.add(new OrderItems(1, 0.5));
        orderItems.add(new OrderItems(1, 1.5));
        orderItems.add(new OrderItems(2, 1));
        orderItems.add(new OrderItems(2, 0.5));
        // java 17 feature to define key easily
        record ItemKey(int id, double portion) {
        }
        Map<ItemKey, GroupedOrderItems> m = orderItems.stream().collect(
                Collectors.groupingBy(
                        // group by ItemKey
                        i -> new ItemKey(i.id, i.portion),
                        // reducing the OrderItems with same key
                        Collectors.reducing(
                                new GroupedOrderItems(0, 0.0, 0L),
                                a -> new GroupedOrderItems(a.id, a.portion, 1),
                                // combine 2 GroupedOrderItems
                                (b, c) -> new GroupedOrderItems(c.id,
                                        c.portion,
                                        b.amount + c.amount)
                        )
                )
        );
        m.entrySet().forEach(e -> System.out.println(e.getValue()));
    }

    public static class OrderItems {
        public int id;
        public double portion;

        public OrderItems(int id, double portion) {
            this.id = id;
            this.portion = portion;
        }
    }

    public static class GroupedOrderItems {
        public int id;
        public double portion;
        public long amount;

        public GroupedOrderItems(int id, double portion, long amount) {
            this.id = id;
            this.portion = portion;
            this.amount = amount;
        }

        @Override
        public String toString() {
            return "GroupedOrderItems{" +
                    "id=" + id +
                    ", portion=" + portion +
                    ", amount=" + amount +
                    '}';
        }
    }
}

0
投票

我的解决方案是这样的:

Map<Integer, Map<Double, Long>> collect = orderItems.stream()
                    .collect(Collectors.groupingBy(OrderItems::getId, Collectors.groupingBy(OrderItems::getPortion, Collectors.counting())));
            System.out.println(collect);

            List<NewOrderItems> newOrderItems = new ArrayList<>();

            collect.forEach((k,v)->{
                    v.forEach((x,y)->{
                           NewOrderItems newOrderitems=new NewOrderItems(k,x,y);
                           newOrderItems.add(newOrderitems);
                    });
            });
            newOrderItems.forEach(System.out::println);

控制台:

NewItems{id=1, portion=0.5, amount=2}
NewItems{id=1, portion=1.5, amount=1}
NewItems{id=2, portion=0.5, amount=1}
NewItems{id=2, portion=1.0, amount=2}

0
投票

首先分组。你会得到一张地图。 OrderItems 作为键,List 作为值。然后算一下。最后排序。

看不懂的地方请检查。

    public static void main(String[] args) {
        List<OrderItems> orderItems = new ArrayList<>();
        orderItems.add(new OrderItems(1, 0.5));
        orderItems.add(new OrderItems(2, 1));
        orderItems.add(new OrderItems(1, 0.5));
        orderItems.add(new OrderItems(1, 1.5));
        orderItems.add(new OrderItems(2, 1));
        orderItems.add(new OrderItems(2, 0.5));


        final List<NewOrderItems> collect = orderItems.stream().collect(Collectors.groupingBy(x -> x))
                .entrySet().stream().map(x -> {
                    NewOrderItems newOrderItems = new NewOrderItems();
                    newOrderItems.setId(x.getKey().id);
                    newOrderItems.setPortion(x.getKey().portion);
                    newOrderItems.setAmount(x.getValue().size());
                    return newOrderItems;
                })
                .sorted(new Comparator<NewOrderItems>() {
                    @Override
                    public int compare(NewOrderItems o1, NewOrderItems o2) {
                        return o1.id - o2.id;
                    }
                })
                .collect(Collectors.toList());
        System.out.println(collect);
    }

-1
投票
Map<String, NewOrderItems> collect4 = orderItems.stream().collect(groupingBy(CollectorsAPi::orderUniqueKey,collectingAndThen(toList(), CollectorsAPi::orderDownstream)));



private static NewOrderItems orderDownstream(List<OrderItems> orderItems) {
    OrderItems orderItem= orderItems.stream().findFirst().orElseThrow();
    NewOrderItems newOrderItems = new NewOrderItems(orderItem.getId(),orderItem.getPortion(),orderItems.size());
    return newOrderItems;
}

private static String orderUniqueKey(OrderItems orderItems ) {
    return String.valueOf(orderItems.getId()).concat("-"+Double.toString(orderItems.getPortion()));
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.