2017-05-21 6 views
2

私はアクティビティのリスト(アクティビティ)を持っており、期間や期間ではないMap(String, DateTime)DateTimeの形式)のデータ構造を決定したいと考えています。各アクティビティについて、モニタリング期間にわたって合計継続時間が計算されます。ストリーム内の参照メソッドにパラメータを送る方法(java 8)?

アクティビティのクラスは、activityLabel(String),startTime(DateTime)endTime(DateTime)です。私はjoda時間を使います。 これは私がやっていることです:

Map<String, DateTime> durations = activities.stream().collect(Collectors.toMap(
            it -> it.activityLabel, 
            it ->new DateTime(0,0,0,0,0,0) 
           //,DateTime::plus 
           )); 

私はDateTime plus(ReadablePeriod period)または DateTime plus(ReadableDuration duration)使用する必要があると思いますが、私はメソッド参照に型持続時間や期間のパラメータを送信する方法がわかりません。

この結果はどのように達成できますか?

EDIT:入力の場合:

2011-12-04 3時00分00秒2011スリーピング

2011-12-03午前一時00分00秒2011年12月3日午前9時00分00秒-12-04午前10時30分00秒私は出力を持っている必要があり

スリーピング:0-0-0午後3時30分00秒(年、月、日、時間、分、秒)

+2

なぜプラス?あなたは 'endTime - startTime'をやってはいけないのですか? – Eugene

+1

DateTimeを使ってどのように期間を表現するのか分かりません。 2017年5月21日のニューヨークタイムゾーンでの期間は、まったく期間ではありません。 –

+0

私はプラス(endTime-startTime)を意味します – SomeoneNew

答えて

3

コードスリーピング(ピリオドを使用)は次のようになります。

Map<String, Period> map = activities.stream() 
      .collect(Collectors.toMap(Activity::activityLabel, ac -> new Period(ac.getStartTime(), ac.getEndTime()), 
        (left, right) -> left.plus(right))); 

実際にPeriodを文字列として出力する場合は、PeriodFormatterが必要です。

private static PeriodFormatter periodFormatter() { 
    return new PeriodFormatterBuilder() 
      .printZeroAlways() 
      .minimumPrintedDigits(2) 
      .appendYears().appendSeparator("-") 
      .appendMonths().appendSeparator("-") 
      .appendDays().appendLiteral(" ") 
      .appendHours().appendSeparator(":") 
      .appendMinutes().appendSeparator(":") 
      .appendSeconds().toFormatter(); 
} 

そして、あなたのコードはより次のようになります。あなたは本当にDateTimeないPeriodである必要があることをコメントで述べたように

Map<String, String> map = activities.stream() 
      .collect(Collectors.collectingAndThen(
        Collectors.toMap(
          Activity::getLabel, 
          ac -> new Period(ac.getStartTime(), ac.getEndTime()), 
          Period::plus), 
        m -> m.entrySet().stream().collect(Collectors.toMap(
          Entry::getKey, 
          e -> e.getValue().toString(periodFormatter))))); 

    System.out.println(map); // {Sleeping=00-00-00 15:30:00 
+0

まず、上院議員。確かに、私の最初の答えはあなたのものともっと似ています。しかし、OPには 'DateTime'が必要なので、私は' groupingBy'を使って答えを変えました。 'groupingBy'を使ってストリームを2回作成するのを避け、' to'Map'よりも簡単に 'Period'sこの場合。 –

1

DateTime以来

DateTime.plus(DateTime)/DateTime.minus(DateTime)のためのAPIを持っていませんが、plus/minusDateTimePeriod、あなたはDateTimeを開始する必要があることができ、かつCollectors apiを使用してコードは、より効率的であるgroupingBytoMapを交換していますあなたのケースでタスクを実行するための表現

DateTime start = DateTime.now(); 

Map<String, DateTime> result = list.stream().collect(Collectors.groupingBy(
    it -> it.activityLabel, 
    Collectors.mapping(
     it -> new Period(it.startTime, it.endTime), 
     // the important section is here: 
     // 1. merge all of periods by using reducing 
     // 2. convert a Period to a DateTime by collectingAndThen 
     Collectors.collectingAndThen(
       Collectors.reducing(Period.ZERO, Period::plus), 
       start::plus 
     ) 
    ) 
)); 
+0

私はあなたのことを理解しています。私はDateTimeを使ってそれをやっている方法を見つけようとしていたので私は再び尋ねました...もっと適切な理由でPeriodを使用すると思います。 – SomeoneNew

+0

@ ProgramerGirl1996こんにちは、 'Period'を' DateTime'に変換できますが、 'DateTime'を開始すると、[plus](http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html#plus(org.joda.time.ReadablePeriod))a 'Period'を' DateTime'を返す 'start.plus(period)'として返します。 –

+2

@ holi-javaこれは、 'DateTime'がスレッドセーフであるため(少なくともドキュメント化されているため)のみ動作します。 ... – Eugene

関連する問題