虽然其他人已经回答了为什么
Math.max
不是可变参数的问题,但他们没有回答为什么在引入可变参数函数时不创建这样的方法。
我甚至不知道为什么(有一个
未解决的错误报告),所以我只能猜测:
虽然
Math
中没有实现它,但如果我们查看
Collections
,会发现以下方法:
public static <T extends Object & Comparable<? super T>> T max(
Collection<? extends T> coll) {
...
}
尽管类型签名看起来很丑(它需要足够灵活以处理协变和逆变),但可以轻松地与
Collections.max(Arrays.asList(-13, 12, 1337, 9));
一起使用。在所有函数实现完成后,只需将其放置在不同的位置即可。
更好的是:此方法不仅可以处理double,还可以处理实现
Comparable
接口的所有类型。
尽管您提出的解决方案和
Collections
中的解决方案都不是面向对象的,它们只是静态方法。幸运的是,在
JDK8中,这种情况将会改变。
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
int max(List<Integer> list) {
Optional<Integer> opt = list.stream().max((a,b) -> a-b);
return opt.orElse(Integer.MAX_VALUE);
}
max(Arrays.asList(-13, 12, 1337, 9));
max(Arrays.asList());
在即将发布的版本中,收集库在Lambda项目中进行了重新设计,以更加面向对象。在上面的示例中,Lambdas被用来提供一种简单易懂的方法来确定最大元素。以下代码也可以实现相同的功能:
import static java.util.Comparators.naturalOrder;
Arrays.asList(-13, 12, 1337, 9)
.stream()
.max(naturalOrder())
.ifPresent(System.out::println);
可以使用高阶函数reduce
代替max
:
Arrays.asList(-13, 12, 1337, 9)
.stream()
.reduce((a,b) -> a > b ? a : b)
.ifPresent(System.out::println)
另外一个细节是使用 Optional。它是一种类型,可以通过高阶函数的组合来简化错误处理,就像上面的示例所示。
lambda 提案有几个优点,使得不需要实现 Math.max 的可变形式:
- 它是面向对象的
- 它是多态的。这意味着它可以与每种类型的集合(List、Set、Stream、Iterator 等)一起使用
- 它表达能力强,易于理解
- 可以在运行时并行化。只需将 .stream() 改为 .parallelStream()