下面是已经从数据库 Sample 表取出得数据
uid date hour clicks views
1 02-10 18 1 2
1 02-10 19 2 2
1 02-19 08 3 2
2 02-11 18 10 2
2 02-11 19 20 2
现在想要 [ group by ] ( uid, date ), 然后 clicks 求和,views 求和,hour 这一列不要了。
uid date clicks views
1 02-10 3 4
1 02-19 3 2
2 02-11 30 4
另外,如果一个 object 还有其他的字段,groupby 的时候不一定是求和,可能是其他运算。
晚上搜了一大堆都是简单的一个字段的 groupBy,像下面一样,且都是返回某个属性值 Long,
Map<String, Long> countMap = samples.stream()
.collect(
Collectors.groupingBy(o -> o.getUid(),
Collectors.summingLong(Sample::getViews)));
其实我想得到对象(比如 sample 对象),求教
1
lhx2008 2020-02-25 07:28:50 +08:00 via Android
所以要输出什么,你的对象 POJO 怎么写的?
|
2
sumarker 2020-02-25 08:10:58 +08:00
没看懂你的问题是什么?
|
3
Malthael 2020-02-25 08:16:51 +08:00
groupingBy 第二个参数你得自定义合并规则。
|
4
zealinux OP @sumarker
其实我就是想要的是,类似 MySQL 的 group by 两个字段功能,且有些字段是 sum() 操作。 ``` Map<String, Sample> countMap = samples.stream() .collect( Collectors.groupingBy( (这里 groupBy 两个字段,uid, 和 date ) (这里返回是 Sample 对象)); ``` |
5
zealinux OP |
6
lhx2008 2020-02-25 09:38:49 +08:00 via Android
请问你 MAP<string,sample>怎么做到你的意思,先把返回值的类型确定一下
|
7
zhady009 2020-02-25 10:54:23 +08:00
用 toMap 就行了然后第 3 个参数 BinaryOperator 里面 key 一样时你把 clicks 和 views 相加
|
8
qinxi 2020-02-25 11:30:09 +08:00
samples.stream()
.collect( Collectors.groupingBy(T::getId)其实返回值就是 Map<String,List<T>> 你要的 sample 不就在 Map 的 List 里面吗... |
9
hrong 2020-02-25 13:44:32 +08:00
楼主就是来要代码的。。。
<pre> public static void main(String[] args) { Sample s1 = new Sample(); s1.setUuid(1); s1.setDate("2-10"); s1.setHour(18); s1.setClicks(1); s1.setViews(2); Sample s2 = new Sample(); s2.setUuid(1); s2.setDate("2-10"); s2.setHour(19); s2.setClicks(2); s2.setViews(2); Sample s3 = new Sample(); s3.setUuid(1); s3.setDate("2-19"); s3.setHour(8); s3.setClicks(3); s3.setViews(2); Sample s4 = new Sample(); s4.setUuid(2); s4.setDate("2-11"); s4.setHour(18); s4.setClicks(10); s4.setViews(2); Sample s5 = new Sample(); s5.setUuid(2); s5.setDate("2-11"); s5.setHour(19); s5.setClicks(20); s5.setViews(2); Collection<Sample> list = List.of(s1,s2,s3,s4,s5) .stream() .collect(collectingAndThen(toMap((Sample s) -> s.getUuid() + "_" + s.getDate(), Function.identity(), (Sample s, Sample a) -> { int sumClick = s.getClicks() + a.getClicks(); int sumView = s.getViews() + a.getViews(); Sample result = new Sample(); result.setUuid(s.getUuid()); result.setDate(s.getDate()); result.setClicks(sumClick); result.setViews(sumView); return result; }), s -> s.values())); list.forEach(System.out::println); } </pre> |
10
jimotudou 2020-02-25 14:10:23 +08:00
9 楼的可以满足楼主需求,但是你为何不直接在数据库写好 sql,在映射到实体类呢。
|
11
chanchan 2020-02-25 14:22:18 +08:00
Map<Integer, Map<String, Map<String,Integer>>> collect2 = list.stream().
collect(Collectors.groupingBy(Sample::getUid, Collectors.toMap(Sample::getDate,v -> { HashMap<String,Integer> map = new HashMap<String,Integer>(); map.put("clicks", v.getClicks()==null?0:v.getClicks()); map.put("views", v.getViews()==null?0:v.getViews()); return map; },(a,b) -> { a.put("clicks", a.get("clicks")+a.get("clicks")); b.put("views", a.get("views")+a.get("views")); return a; }))); 想了好一会儿... |
12
Rwing 2020-02-25 14:40:44 +08:00
c#欢迎你
https://dotnetfiddle.net/zUSwU7 ``` var data = new List<Sample> { new Sample {id = 1, date = "02-10", clicks = 1, views = 2}, new Sample {id = 1, date = "02-10", clicks = 2, views = 2}, new Sample {id = 1, date = "02-19", clicks = 3, views = 2}, new Sample {id = 2, date = "02-11", clicks = 4, views = 2}, new Sample {id = 2, date = "02-11", clicks = 5, views = 2}, }; var result = data.GroupBy(i => new { i.id, i.date }) .Select(g => new Sample { id = g.Key.id, date = g.Key.date, clicks = g.Sum(i => i.clicks), views = g.Sum(i => i.views), }); ``` |