我有一个使用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流式传输结果然后我流式传输收集的地图。比较器似乎也很突出。当然,我可以用它来制作课程,但也许还有另一种解决方案。
答案 0 :(得分:5)
我不能说JOOQ部分,但Stream API部分看起来很好。您必须在分类之前中间收集以了解计数。请注意,此类比较器已在JDK中实现:它是Map.Entry.comparingByValue()
。您可以使用它(添加Comparator.reverseOrder()
参数以反向排序):
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(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.forEach(e -> System.out.println(String.format("%13s: %3d", e.getKey(), e.getValue())));
答案 1 :(得分:2)
除非这是更复杂查询的大幅简化版本,否则我将所有逻辑都移到SQL。等效的SQL查询(使用Oracle方言)是:
SELECT PREFIX, COUNT(*)
FROM (
SELECT SUBSTR(USER_NAME, 1, INSTR(USER_NAME, '-') - 1) AS PREFIX
FROM CWD_USER
) T
GROUP BY PREFIX
ORDER BY COUNT(*)
或者,使用jOOQ:
sql.select(field("PREFIX", String.class), count())
.from(
select(substring(
field("USER_NAME", String.class),
inline(1),
position(field("USER_NAME", String.class), inline("-")).sub(inline(1))
).as("PREFIX"))
.from(table("CWD_USER"))
)
.groupBy(field("PREFIX", String.class))
.orderBy(count())
.fetch();