根据条件拆分对象集合 [英] Split a collection of objects based on a condition
问题描述
我有一个要添加到袋子中的物品清单,袋子容量为100数量
I have a list of objects to be added in a bag and bags capacity is 100 qty
物品和袋子如下所示
public class MyObject{
String id;
int qty;
}
public class MyBag{
String id;
int qty;
}
有什么方法可以使用Java 8流在数量限制上将MyObject分成多个MyBags分组
Is there any way to split MyObject in multiple MyBags grouping on the qty limit using Java 8 streams
例如:myObjects是
For example: myObjects are
[myObject1:{id1, 150},
myObject2:{id2, 30},
myObject3:{id3, 150}]
因为包的容量为100. 袋子应分组为
Since bag has a capacity of 100. Bags should be grouped as
[ bag1:[{id1, 100}],
bag2:[{id1, 50},{id2, 30},{id3, 20}],
bag3:[{id3, 100}],
bag4:[{id3, 30}]]
推荐答案
在注释中维护该解决方案并非易事.下面是一个接近您想要的示例.首先,我只使用头等舱MyObject
并对其进行了一些更改.
As it was maintained in comments the solution won't be easy. Below is an example that is close to what you want. First I used only first class MyObject
and change it a bit.
public class MyObject{
String id;
int qty;
public MyObject(String id, int qty) {
this.id = id;
this.qty = qty;
}
@Override
public String toString() {
return "MyObject{" +
"id='" + id + '\'' +
", qty=" + qty +
'}';
}
}
初始化代码:
List<MyObject> myObjects = Arrays.asList(
new MyObject("id1", 150),
new MyObject("id2", 30),
new MyObject("id3", 150)
);
和主要代码.在flatMap
中,将MyObject
与大qty
分开.之后,将对象收集到具有给定限制的列表中.输出与您想要的不完全相同.第三个列表包含两个标识符为id3
的对象.
And the main code. In flatMap
there is splitting MyObject
with large qty
. After that objects are collected to lists with given limit. The output isn't exactly as you want. The third list includes two objects with identifier id3
.
[MyObject{id='id1', qty=100}]
[MyObject{id='id1', qty=50}, MyObject{id='id2', qty=30}, MyObject{id='id3', qty=20}]
[MyObject{id='id3', qty=80}, MyObject{id='id3', qty=20}]
[MyObject{id='id3', qty=30}]
LinkedList<List<MyObject>> firstCollection = myObjects.stream()
.flatMap(o -> o.qty < 100 ? Stream.of(o) : IntStream.range(0, (o.qty / 100 + 1))
.mapToObj(x -> new MyObject(o.id, x < o.qty / 100 ? 100 : o.qty % 100))
)
.collect(
Collector.of(
LinkedList::new,
(a, b) -> Optional.of(a).filter(Predicate.not(List::isEmpty))
.map(l -> l.getLast().stream().map(o -> o.qty).reduce(Integer::sum).get())
.filter(lastSum -> lastSum < 100)
.ifPresentOrElse(lastSum -> {
int maxQty = 100 - lastSum;
if (maxQty >= b.qty) {
a.getLast().add(b);
} else {
a.getLast().add(new MyObject(b.id, maxQty));
a.add(new ArrayList<>(List.of(new MyObject(b.id, b.qty - maxQty))));
}
}, () -> a.add(new ArrayList<>(List.of(b))))
,
(a, b) -> { throw new UnsupportedOperationException();}
)
);
firstCollection.forEach(System.out::println);
这篇关于根据条件拆分对象集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!