我有以下
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}
我们可以利用
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 +
'}';
}
}
}
我的解决方案是这样的:
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}
首先分组。你会得到一张地图。 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);
}
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()));
}