【问题标题】:How to put .min() or .max() as method parameter for a stream?如何将 .min() 或 .max() 作为流的方法参数?
【发布时间】:2019-12-07 22:23:52
【问题描述】:

如何在如下代码中将.min() 或.max() 表达式作为方法参数传递:

给定代码:

private LocalDate getMaxDate() {
    LocalDate maxdate = dates.stream()
              .max( Comparator.comparing( LocalDate::toEpochDay ) )
              .get();
}

private LocalDate getMinDate() {
    LocalDate maxdate = dates.stream()
              .min( Comparator.comparing( LocalDate::toEpochDay ) )
              .get();
}

我希望拥有的代码:

private LocalDate getDate(SomeType _EXPR_){
        LocalDate maxdate = dates.stream()
                  ._EXPR_( Comparator.comparing( LocalDate::toEpochDay ) )
                  .get();
    }

提示:_EXPR_ 应为.min(),有时为.max()

【问题讨论】:

  • 好吧,您可以将SomeType 设为一个枚举(或只是一个布尔值)以在最小值和最大值之间切换,始终使用.min() 或.max(),并在需要时反转比较器。但是,仅使用两种不同的方法有什么问题?与将“表达式”作为参数传递相比,它们更具可读性和使用安全性。

标签: java java-8 java-stream max min


【解决方案1】:

方法是

private LocalDate getDate(Function<Comparator<LocalDate>, BinaryOperator<LocalDate>> f) {
  return dates.stream()
              .reduce(f.apply(Comparator.comparing(LocalDate::toEpochDay)))
              .get();
}

要调用它,请使用

getDate(BinaryOperator::maxBy);
getDate(BinaryOperator::minBy);

注意NoSuchElementException 可能会抛出Optional#get。

【讨论】:

    【解决方案2】:

    这是另一个选择:

    private LocalDate getMinOrMaxDate (boolean max) {
        Stream<LocalDate> ds = dates.stream();
        Comparator<LocalDate> comp = Comparator.comparing(LocalDate::toEpochDay);
        return (max ? ds.max(comp) : ds.min(comp)).get();
    }
    

    【讨论】:

    • 如果我们关心对象数量,这会更好,因为这个版本不会创建任何额外的对象。我只想用枚举替换“魔术”true:false 常量(真遗憾 Java 还没有枚举)。
    • @M.Prokhorov 如果有一个枚举,它将由哪些常量组成? MIN, MAX?这些常量在更广泛的、无上下文的意义上意味着什么?
    【解决方案3】:

    您可以直接传入boolean,并根据需要调用Comparator#reversed():

    private LocalDate getDate(boolean max) {
        Comparator<LocalDate> comparator = Comparator.comparing(LocalDate::toEpochDay);
        if (!max) comparator = comparator.reversed();
        return dates.stream().max(comparator).get();
    }
    

    也可以使用enum 而不是boolean 作为参数来实现相同的行为。这可能对可读性更好。

    【讨论】:

      【解决方案4】:

      如果我正确理解你的问题,你想传递 .min() 。 Stream 类中的 .max() 方法。这可以像这样完成:

         private LocalDate getDate(BiFunction<Stream, Comparator<? super LocalDate>, Optional<LocalDate>> _EXPR_){
             return _EXPR_.apply(dates.stream(), Comparator.comparing(LocalDate::toEpochDay)).get();
         }
      

      然后可以调用

      getDate(Stream::min);
      getDate(Stream::max);
      

      这种方法相当不安全,不是很优雅,并且比使用 getMin() 和 getMax() 方法增加了更多的复杂性。为了可读性,可能值得考虑保留这两种方法。

      如果您真的想避免重复代码和/或泛化方法,我可能会采用类似 cameron1024 建议的解决方案。

      【讨论】:

      • 这个方法怎么称呼?
      猜你喜欢
      • 2021-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 1970-01-01
      • 2017-09-22
      • 1970-01-01
      相关资源
      最近更新 更多