【问题标题】:How to send parameters to a reference method in a stream (java 8)?如何将参数发送到流中的引用方法(java 8)?
【发布时间】:2017-05-21 13:48:00
【问题描述】:

我有一个活动列表(活动),我想确定一个映射形式为Map(String, DateTime)(不是持续时间或期间;DateTime 这是必须的)的数据结构。对于每项活动,在监控期间计算的总持续时间。

类 Activity 有: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) ,但我不知道如何将 Duration 或 Period 类型的参数发送到方法引用。

我怎样才能达到这个结果?

编辑:对于输入:

2011-12-03 01:00:00 2011-12-03 9:00:00 睡觉

2011-12-04 03:00:00 2011-12-04 10:30:00 睡觉

我应该有输出: Sleeping 0-0-0 15:30:00 (years,months,days,hours,minutes,seconds)

【问题讨论】:

  • 为什么加上?你不应该做endTime - startTime吗?
  • 我真的不明白你应该如何使用 DateTime 来表示持续时间。纽约时区的 2017 年 5 月 21 日根本不是持续时间。
  • 我的意思是加(endTime-startTime)
  • @ProgramerGirl1996 谁/什么需要??.plus(endTime-startTime)?通常endTime - startTimeDuration 而不是DateTime
  • 好吧,您可以决定始终使用相同的时区 (UTC),并且 2 小时的持续时间将由 DateTime 纪元 + 2 小时 UTC 表示,但这真的不是一个好主意.为什么不使用适当的类:Duration?

标签: java lambda java-8 java-stream jodatime


【解决方案1】:

代码(使用句点)如下所示:

 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();
}

然后你的代码看起来更像这样:

 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

【讨论】:

  • 首先,赞成,先生。确实,我的第一个答案与您的更相似。但是 OP 需要DateTime,所以我将答案更改为使用groupingBy,我发现您也可以使用groupingBy 来避免两次创建流并使代码比toMap 更简单,当显示Periods在这种情况下。
【解决方案2】:

正如您在评论中提到的,您真正需要的是 DateTime 而不是 Period

由于DateTime 没有DateTime.plus(DateTime)/DateTime.minus(DateTime) 的api,但是您可以在DateTime 上使用plus / minusPeriod,那么您需要DateTime 才能启动,并且使用Collectors api 的代码将toMap 替换为groupingBy,这在您的情况下更有效表现力

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
        )
    )
));

【讨论】:

  • 我明白你的意思。我再次问,因为我试图找到一种使用 DateTime 的方法......我想我会使用 Period 因为它更合适
  • @ProgramerGirl1996 嗨,您可以将Period 转换为DateTime,但您需要DateTime 才能启动,然后您可以将plus 转换为Period 为:start.plus(period)返回一个DateTime
  • @holi-java 这只会起作用,因为DateTime 是线程安全的(至少它是这样记录的)。如果您添加的并行流是...
  • @Eugene 感谢您的反馈,但DateTime 是一个值对象,它没有副作用。我减少了Periods 而不是DateTimes。
  • @holi-java 我的意思实际上是这样的:int i[] = { 0 }; Stream.of(1, 2, 3, 4) .parallel() .collect(Collectors.mapping(x -&gt; { ++i[0]; return x; }, Collectors.toList())); 完成此操作后,无法保证i[0] == 4。你的情况也一样。 但是 因为DateTime 是线程安全的,所以你没问题。这就像使用AtomicInteger 而不是i[]
猜你喜欢
  • 2020-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2019-03-12
相关资源
最近更新 更多