hackugyo
1/4/2016 - 2:31 AM

RxのgroupByが、groupっつってんのにKey / ValueのHashMapをすなおに返す方法がなさそう(途中で止まってしまう)ので、いったんPairのListの形でtoList().toBlocking().single()で吐き出させて、しかるのちにHashMapに

RxのgroupByが、groupっつってんのにKey / ValueのHashMapをすなおに返す方法がなさそう(途中で止まってしまう)ので、いったんPairのListの形でtoList().toBlocking().single()で吐き出させて、しかるのちにHashMapに入れるようにした。AbstractMap.SimpleEntryのかわりにPairを使ってもいい。


import java.util.AbstractMap;
import java.util.HashMap;
import java.util.List;

import rx.Observable;
import rx.functions.Func1;
import rx.functions.Func2;
import rx.observables.GroupedObservable;


    /**
     * Observableの中身を指定のgrouperでgroupByして、HashMapに入れて返します。
     * @param observable
     * @param grouper
     * @param <K> groupByのキーの型
     * @param <V> groupByの値の型
     * @return HashMap(キーごとに対応する値のListが入っている)
     * @see <a href="http://stackoverflow.com/a/33234243">参考リンク</a>
     */
    /**
     * Observableの中身を指定のgrouperでgroupByして、HashMapに入れて返します。
     * @param observable
     * @param grouper
     * @param <K> groupByのキーの型
     * @param <V> groupByの値の型
     * @return HashMap(キーごとに対応する値のListが入っている)
     * @see <a href="http://stackoverflow.com/a/33234243">参考リンク</a>
     */
    public static <K, V> HashMap<K, List<V>> groupBy(Observable<V> observable, Func1<V, K> grouper) {
        HashMap<K, List<V>> result = observable.groupBy(grouper)
                .flatMap(new Func1<GroupedObservable<K, V>, Observable<AbstractMap.SimpleEntry<K, List<V>>>>() {
                    @Override
                    public Observable<AbstractMap.SimpleEntry<K, List<V>>> call(final GroupedObservable<K, V> grouped) {
                        return grouped.toList().map(new Func1<List<V>, AbstractMap.SimpleEntry<K, List<V>>>() {
                            @Override
                            public AbstractMap.SimpleEntry<K, List<V>> call(List<V> list) {
                                return new AbstractMap.SimpleEntry<>(grouped.getKey(), list);
                            }
                        });
                    }
                })
                .reduce(new HashMap<K, List<V>>(),
                        new Func2<HashMap<K, List<V>>, AbstractMap.SimpleEntry<K, List<V>>, HashMap<K, List<V>>>() {
                            @Override
                            public HashMap<K, List<V>> call(HashMap<K, List<V>> result, AbstractMap.SimpleEntry<K, List<V>> entry) {
                                result.put(entry.getKey(), entry.getValue());
                                return result;
                            }
                        })
                .toBlocking()
                .single();
        return result;
    }