我有对象列表,比如类文档:
class Document {
private final String id;
private final int length;
public Document(String id, int length) {
this.id = id;
this.length = length;
}
public int getLength() {
return length;
}
}
手头的任务是将它们分组在信封中,以便页数(document.length)不超过某个数字。
class Envelope {
private final List<Document> documents = new ArrayList<>();
}
举个例子,如果我有以下文件列表:
Document doc0 = new Document("doc0", 2);
Document doc1 = new Document("doc1", 5);
Document doc2 = new Document("doc2", 5);
Document doc3 = new Document("doc3", 5);
信封中的最大页数是7页,比我预期的3个包含以下文档的信封还要多:
Assert.assertEquals(3, envelopeList.size());
Assert.assertEquals(2, envelopeList.get(0).getDocuments().size()); // doc0, doc1
Assert.assertEquals(1, envelopeList.get(1).getDocuments().size()); // doc2
Assert.assertEquals(1, envelopeList.get(2).getDocuments().size()); // doc3
我已经用传统的for循环和if实现了这一点,但问题是,有没有可能用流和收集器实现更优雅的方式呢?
谢谢并致以最诚挚的问候
达利博尔
1条答案
按热度按时间zpqajqem1#
对于基于长度的批处理文档,我们需要保持累积长度的状态。
Streams
当需要维护外部状态时,不是最佳选择,自定义循环应该是更简单有效的选择。如果我们强制匹配,这个场景中的流
DocumentSpliterator
变化如下:说明:
helper
保持累计长度,并在超过我使用的最大值时提供一个新的bucket索引IntUnaryOperator
接口在这里。或者,我们可以使用任何采用int
参数并返回int
.关于溪流,
Document
Map到SimpleEntry
关于bucketindex和文档。溪流
SimpleEntry
首先根据bucketindex进行分组。另一个Collector
改变了Document
对于一个特定的bucketindex到Couvert
. 输出collect()
是Map<Integer,Couvert>
最后是Collection
的Couvert
转换为列表并返回。注意:对于这个实现,我删除了
front
参数,并将其作为docs
列表。