根据条件拆分对象集合 [英] Split a collection of objects based on a condition

查看:103
本文介绍了根据条件拆分对象集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个要添加到袋子中的物品清单,袋子容量为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆