【发布时间】:2015-12-20 09:04:50
【问题描述】:
我结合使用 jooq 查询数据库和使用流对结果进行后处理。但是我觉得我的代码不是很可读,也不够简洁。如何以更好地表达我的意图的方式改进我的代码。
sql
.select(field("USER_NAME", String.class))
.from(table("CWD_USER"))
.fetch()
.stream()
.map(f -> f.getValue(field("USER_NAME", String.class)))
.collect(Collectors.groupingBy(s -> StringUtils.split(s, "-")[0], Collectors.counting()))
.entrySet().stream()
.sorted(new java.util.Comparator<Entry<String, Long>>() {
@Override
public int compare(Entry<String, Long> o1,
Entry<String, Long> o2) {
return o2.getValue().compareTo(o1.getValue());
}
})
.forEach(e -> System.out.println(String.format("%13s: %3d", e.getKey(), e.getValue())));
首先,我遇到了多流媒体的问题。我首先从 jooq 流式传输结果,然后流式传输收集的地图。比较器似乎也很突出。当然我可以用它来做一门课,但也许还有另一种解决方案。
【问题讨论】:
-
即使您不知道
Map.Entry.comparingByValue(…)的存在,我也不明白您为什么认为必须为Comparator使用内部类,正如您已经证明的那样了解代码中其他位置的 lambda 表达式。 -
仅供参考,对应的 lambda 应该是
.sorted( (o1, o2) -> o2.getValue().compareTo( o1.getValue() ) )。感谢@Holger 指出这一点。 -
I first stream the result from jooq then I stream the collected map- 没有。您从 jooq 流式传输结果,仅此而已。您的示例中没有显示其他流,即一个带有几个中间操作和一个终端操作的单个流。这就是流的工作方式。如果你想“避免”流的核心功能,你需要使用经典的 foreach/for/while - 循环。但老实说:那将是一个降级......流非常简洁和漂亮 - 你自己的代码证明了这一点。相同的功能需要至少 100 行没有流的代码。 -
@specializt:仔细看看。中间有一个
collect。这是第一个流的终端操作,entrySet().stream()创建一个新流。没关系,因为这是不可避免的。 -
中间映射是不可避免的,尤其是后面的排序,因为这些操作必须在管道中的下一步执行之前完成,否则它无法知道它是否已经找到 min-元素
标签: java-8 java-stream jooq readability