如何将.min()或.max()作为流的方法参数?

3

如何将 .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()

4
你可以将 SomeType 定义为枚举类型(或者只使用布尔值),以此来切换最小值和最大值,总是使用 .min().max() 方法,并在需要时反转比较器。但是,直接使用这两种不同的方法有什么问题吗?相比于将“表达式”作为参数传递,它们更易读且更安全。 - Thomas
4个回答

5
该方法是:
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();
}

如果我们关心对象计数,那么这种方法会更好,因为这个版本不会创建任何额外的对象。我只是想用枚举替换“magic”true:false常量(很遗憾Java还没有一个)。 - M. Prokhorov
@M.Prokhorov 如果有一个枚举,它应该由哪些常量组成? MINMAX?这些常量在更广泛、没有上下文的意义上意味着什么? - Andrew Tobilko

0

您可以传递一个布尔值,然后根据需要调用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作为参数来实现相同的行为。这对于可读性可能更好。


0
如果我正确理解了您的问题,您想从Stream类传递.min()或.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建议的解决方案。


你会如何称呼这个方法? - Andrew Tobilko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接