2016-01-30 11 views
10

Map<String, Double>をJava 8のList<Pair<String, Double>>に変換する方法はありますか?マップをJavaのリストに変換する方法8

私はこの実装を書いたが、それは、私はそれが作品.collect(Collectors.someMethod())を使用しなければならないことを知っている

Map<String, Double> implicitDataSum = new ConcurrentHashMap<>(); 
//.... 
List<Pair<String, Double>> mostRelevantTitles = new ArrayList<>(); 
implicitDataSum.entrySet().stream(). 
       .sorted(Comparator.comparing(e -> -e.getValue())) 
       .forEachOrdered(e -> mostRelevantTitles.add(new Pair<>(e.getKey(), e.getValue()))); 

return mostRelevantTitles; 

効率的ではありません。しかし、私はそれを行う方法を理解していません。

答えて

16

まあ、Pairの要素をListに集めたいとします。つまり、Stream<Map.Entry<String, Double>>Stream<Pair<String, Double>>にマッピングする必要があります。

これはmap操作を用いて行われる:このストリームの要素に与えられた関数を適用した結果からなるストリームを返し

。この場合

、関数は、Pair<String, Double>Map.Entry<String, Double>を変換する関数です。

最後に、それをListに収集したいので、組み込みのtoList()コレクタを使用できます。

List<Pair<String, Double>> mostRelevantTitles = 
    implicitDataSum.entrySet() 
        .stream() 
        .sorted(Comparator.comparing(e -> -e.getValue())) 
        .map(e -> new Pair<>(e.getKey(), e.getValue())) 
        .collect(Collectors.toList()); 

あなたはMap.Entry.comparingByValue(Comparator.reverseOrder())によってコンパレータComparator.comparing(e -> -e.getValue())を置き換えることができます注。あなたは効率的実装をしたい場合、あなたはこのことを考慮すべきであることを

+1

'-e.getValue()'はNaNを並べ替えないことに注意してください。フォワードオーダーは、リストの最後に 'Double.NaN'値があると仮定します。単項マイナスを使用すると、* NaNを除くすべてのものを元に戻します。リストの末尾にはまだ入ります。 –

+0

ええ、 'Map.Entry.comparingByValue(Comparator.reverseOrder())'または 'Collections.reverseOrder(Map.Entry.comparingByValue())'です。負の値を比較することが意図されている場合[Tagirはその違いを説明しました](http://stackoverflow.com/questions/35107550/how-to-convert-map-to-list-in-java-8#comment57966768_35107595)、コンパレータ.comparingDouble'は、値の再ボックス化を避けるために優先されるべきです。 – Holger

5

注:

List<Pair<String, Double>> mostRelevantTitles = 
    implicitDataSum.entrySet() 
        .stream() 
        .map(e -> new Pair<>(e.getKey(), e.getValue())) 
        .collect(Collectors.toList()); 
mostRelevantTitles.sort(Comparators.comparing(Pair::getSecond, Comparator.reverseOrder())); 

は、私はあなたのPairクラスがgetSecondゲッターを持っていることを前提としています。

sorted()ストリームパイプラインステップを使用すると、中間バッファを作成し、そのバッファにすべてを格納し、配列に変換し、その配列をソートしてから、結果をArrayListに格納します。私のアプローチは、機能はほとんどありませんが、データをターゲットArrayListに直接格納し、追加のコピーを行わずにインプレースでソートします。だから私のソリューションは、時間と中間メモリを取る時間が少なくなります。

関連する問題