グルーピング&ソートの続き

先日のグルーピング&ソートに続いて、、、
グルーピングした時にソートもする。 - 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());
    })
)));

ソートもされるけど、何だか遅そう。。