先日のグルーピング&ソートに続いて、、、
グルーピングした時にソートもする。 - Oboe吹きプログラマの黙示録
同じく Foo なるクラスオブジェクトのリストで、グルーピングして並べた時に、先頭だけキーをそのままで
他をキーが表示されないように置き換えなどの細工をする。
key : value ------------- A : 1 : 2 : 3 B : 11 : 12 C : 31
のように表示できるようにリストを変更したいする。すぐに思いつくのが、groupingBy して作った Map の
entrySet() ストリームを流して、flatMap で、変更する方法、、
List<Foo> results = list.stream().collect(Collectors.groupingBy(t->t.key, Collectors.mapping(u->u, Collectors.toList()))) .entrySet().stream().flatMap(e->{ AtomicInteger i = new AtomicInteger(0); return e.getValue().stream().sorted((o1, o2)->new Integer(o1.value).compareTo(new Integer(o2.value))).map(t->{ if (i.getAndIncrement() > 0) t.key = " "; return t; }); } ).collect(Collectors.toList());
でも、AtomicInteger生成文が入って気持ち悪い。
遅くて効率が悪いかもしれなけど、Stream.concat を使ってみる。
List<Foo> results = list.stream().collect(Collectors.groupingBy(t->t.key, Collectors.mapping(u->u, Collectors.toList()))) .entrySet().stream().flatMap(e->{ List<Foo> _list = e.getValue().stream() .sorted((o1, o2)->new Integer(o1.value).compareTo(new Integer(o2.value))).collect(Collectors.toList()); return Stream.concat(_list.stream().limit(1) , _list.stream().skip(1).map(t->{ t.key = " "; return t; })); }).collect(Collectors.toList());
キーそのものもソートまで実施するなら、こんなんじゃダメなので、
Map<String, List<Foo>> map = list.stream().collect(Collectors.groupingBy(e->e.key, Collectors.mapping(t->t, Collectors.collectingAndThen(Collectors.toCollection(ArrayList::new) , t->{ List<Foo> _list = t.stream().sorted((o1, o2)->new Integer(o1.value) .compareTo(new Integer(o2.value))).collect(Collectors.toList()); return Stream.concat(_list.stream().limit(1), _list.stream().skip(1).map(u->{ u.key = " "; return u; })).collect(Collectors.toList()); }) )));
ソートもされるけど、何だか遅そう。。