【发布时间】:2015-04-06 10:49:15
【问题描述】:
Streams API 中缺少的功能之一是“分区依据”转换,例如Clojure 中定义的。假设我想重现 Hibernate 的 fetch join:我想发出一条 SQL SELECT 语句来从结果中接收这种对象:
class Family {
String surname;
List<String> members;
}
我发出:
SELECT f.name, m.name
FROM Family f JOIN Member m on m.family_id = f.id
ORDER BY f.name
然后我检索(f.name, m.name) 记录的平坦流。现在我需要将其转换为Family 对象流,其中包含其成员列表。假设我已经有一个Stream<ResultRow>;现在我需要将其转换为Stream<List<ResultRow>>,然后通过映射转换将其转换为Stream<Family>。
转换的语义如下:只要提供的鉴别器函数一直返回相同的值,就一直将流收集到List;一旦值发生变化,将List 作为输出流的一个元素发出并开始收集新的List。
希望能写出这样的代码(我已经有了resultStream方法):
Stream<ResultRow> dbStream = resultStream(queryBuilder.createQuery(
"SELECT f.name, m.name"
+ " FROM Family f JOIN Member m on m.family_id = f.id"
+ " ORDER BY f.name"));
Stream<List<ResultRow> partitioned = partitionBy(r -> r.string(0), dbStream);
Stream<Family> = partitioned.map(rs -> {
Family f = new Family(rs.get(0).string(0));
f.members = rs.stream().map(r -> r.string(1)).collect(toList());
return f;
});
不用说,我希望生成的流保持惰性(非物化),因为我希望能够在不达到任何 O(n) 内存限制的情况下处理任何大小的结果集。如果没有这个关键要求,我会对提供的 groupingBy 收集器感到满意。
【问题讨论】:
-
我不确定,但这可能与this problem 相同吗?
-
是的,我相信是的。我实际上正在考虑提及与
groupingBy的相似性和关键区别。但是,提供的解决方案完全不同。
标签: java java-8 java-stream