2016-02-21 14 views
5

月ごとにグループ化してデータを保存するMoveTrackオブジェクトのリストがあります。Map<String, Double>です。私はラムダを学び、ラムダでこの作業をしようと試みています。ラムダを使用してリストをグループ化して合計する

class MoveTrack { 
private Date time; 
private Double movementAmount; 

//getters and setters 
} 

// in my main method 
List<MoveTrack> mveTracking = new ArrayList<>(); 
Map<String, Double> movMap = new HashMap<>(); 

は、だから私は、moveTrackingリストのグループのことができるように、各地図キー=月名(1月、2月、など)と対応する値である移動量と、movMapに値を合計しますその月のダブルスの合計。

+3

ためのコミッター午前さて、あなたはまだ何を試してみましたか?私は 'Stream.collect'と' Collectors.groupingBy'を使いたいと思っています。 –

+1

コレクターズダウンストリームコレクターとしてのダブリング –

+0

@ JonSkeetはい、エラーを除いてgroupByとtoMapを試行しました。特に私が単純なフォーマッタを入れ始めたとき。 – Aeseir

答えて

5

Collectors.groupingByキーをリストの要素の何らかの操作とするマップにリストを縮小することができます。値は、要素の操作に適用されるいくつかの集計関数です。 あなたのケースでは、あなたがこのようなものを使用でき、以下のよう

SimpleDateFormat monthFormatter = new SimpleDateFormat("MMM"); 
Map<String, Double> moveMap = 
    moveTracking.stream() 
       .collect(Collectors.groupingBy 
        (m -> monthFormatter.format(m.getTime()), 
        Collectors.summingDouble(MoveTrack::getMovementAmount))); 
2

使用Collectors.groupingByを:

mveTracking.stream().collect(Collectors.groupingBy(m -> { 
      final Calendar cal = Calendar.getInstance(); 
      cal.setTime(m.getTime()); 
      final int month = cal.get(Calendar.MONTH); 
      return new DateFormatSymbols().getMonths()[month]; 
     }, Collectors.summingDouble(MoveTrack::getMovementAmount))); 

コードあなたのため;)

import java.text.DateFormatSymbols; 
import java.util.ArrayList; 
import java.util.Calendar; 
import java.util.Date; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.stream.Collectors; 

public class GroupList { 
    public static void main(String[] args) { 
     List<MoveTrack> mveTracking = new ArrayList<>(); 
     mveTracking.add(new MoveTrack(new Date(), 10.0d)); 
     mveTracking.add(new MoveTrack(new Date(), 11.0d)); 
     Map<String, Double> movMap = new HashMap<>(); 
     movMap = mveTracking.stream().collect(Collectors.groupingBy(m -> { 
      final Calendar cal = Calendar.getInstance(); 
      cal.setTime(m.getTime()); 
      final int month = cal.get(Calendar.MONTH); 
      return new DateFormatSymbols().getMonths()[month]; 
     }, Collectors.summingDouble(MoveTrack::getMovementAmount))); 
     System.out.println(movMap); 
    } 
} 

final class MoveTrack { 

    private final Date time; 
    private final Double movementAmount; 

    public MoveTrack(final Date time, final Double movementAmount) { 
     this.time = new Date(time.getTime()); 
     this.movementAmount = movementAmount; 
    } 

    public Date getTime() { 
     return time; 
    } 

    public Double getMovementAmount() { 
     return movementAmount; 
    } 
} 
6

を開いている場合第三者のライブラリを使用する場合は、Eclipse CollectionsにはsumByという特殊なメソッドがありますラムダ。

あなたはmoveTrackingのリストについては、EclipseのコレクションからMutableListを使用する場合は、次のように、コードがなります

MutableList<MoveTrack> moveTracking = Lists.mutable.empty(); 
ObjectDoubleMap<String> doubleMap = 
    moveTracking.sumByDouble(MoveTrack::getMonthName, MoveTrack::getMovementAmount); 

それはどこで、どのようにあなたがgetMonthName()を実装するかを決定するのはあなた次第です。 sumByDoubleObjectDoubleMapを返します。つまり、movementAmountdoubleを使用でき、合計時にボックス化されません。

List<MoveTrack>タイプを現在の状態に保ちたい場合は、ListAdapterまたはIterateユーティリティクラスを使用して同じことを達成できます。

List<MoveTrack> list = ...; 
ObjectDoubleMap<String> doubleMap = 
    Iterate.sumByDouble(list, MoveTrack::getMonthName, MoveTrack::getMovementAmount); 

注:私はEclipseのコレクション

関連する問題