当前位置: 首页 > 面试题库 >

为什么Math.max(double a,double b)不可变?

艾泰
2023-03-14
问题内容

为什么Math.max的实现不是可变函数?

可以这样实现:

public class Main {
    public static double max(double... values) {
        double max = Double.NEGATIVE_INFINITY;
        for (double tmp : values) {
            max = max < tmp ? tmp : max;
        }
        return max;
    }

    public static void main(String[] args) {
        // This works fine:
        System.out.println(max(-13, 12, 1337, 9));

        // This doesn't work:
        // System.out.println(Math.max(-13, 12, 1337));
    }
}

没有任何理由为什么不能这样实现?


问题答案:

尽管其他人已经回答了为什么Math.max不是可变参数的问题,但他们没有回答为什么引入可变参数功能时不会创建这种方法的原因。

我什至不知道(有一个开放的bug报告),所以我只能猜测:

的确没有在中实现它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)); // 1337
max(Arrays.asList()); // 2147483647

对于即将发布的版本,集合库在Project
Lambda
中进行了重新设计,使其更加面向对象。在上面的示例中,Lambda用于提供一种简单易读的方式来确定max元素。以下内容也可以工作:

import static java.util.Comparators.naturalOrder;

Arrays.asList(-13, 12, 1337, 9)
  .stream()
  .max(naturalOrder())
  .ifPresent(System.out::println); // 1337

除了max使用高阶函数外,还可以使用reduce

Arrays.asList(-13, 12, 1337, 9)
  .stream()
  .reduce((a,b) -> a > b ? a : b)
  .ifPresent(System.out::println); // 1337

另一个细节是的使用Optional。由于上面示例中所示的高阶函数的组成,它是一种简化错误处理的类型。

lambda提案具有多个优点,因此无需实现可变形式的Math.max:

  1. 它是面向对象的
  2. 它是多态的。这意味着它可以与每一种类型的集合的被使用(ListSetStreamIterator等等)
  3. 富有表现力且易于理解
  4. 它允许即时并行化。只需更改.stream().parallelStream()


 类似资料:
  • 本文向大家介绍Math.min() < Math.max() 返回结果是什么?为什么?相关面试题,主要包含被问及Math.min() < Math.max() 返回结果是什么?为什么?时的应答技巧和注意事项,需要的朋友参考一下 返回,因为返回,返回。 猜测的实现方式大致如下: 接受不定项参数,当参数只有一个的时候,例如,那么这个需要和(js中最小的数)进行比较,所以结果返回,哪怕传入的值再小,单个

  • 本文向大家介绍String 为什 么是不可变的?相关面试题,主要包含被问及String 为什 么是不可变的?时的应答技巧和注意事项,需要的朋友参考一下 简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串,`private final char value[]`,所以 String 对象是不可变的。而StringBuilder 与 StringBuffer 都继承自 Ab

  • 问题内容: 我正在观看有关Java的演示,有一次讲师说: “可变性还可以,共享很好,共享可变性是魔鬼的工作。” 他指的是以下代码,他认为这是“极度坏习惯”: 然后,他着手编写应使用的代码,即: 我不明白为什么第一段代码是“不良习惯”。对我来说,他们都实现了相同的目标。 问题答案: 当执行并行处理时,该问题就起作用了。 在使用流时,这不必要地使用了 副作用, 但如果正确使用,并非所有副作用都不好,因

  • 我正在看一个关于Java的演讲,有一次,讲师说: “可变是可以的,共享是好事,共享可变是魔鬼的工作。” 他所指的就是以下代码,他认为这是一个“极其糟糕的习惯”: 然后,他继续编写应该使用的代码,即: 我不明白为什么第一段代码是“坏习惯”。对我来说,他们都达到了相同的目标。

  • 问题内容: 创建数组时,无法更改其大小;它是固定的。好的,看起来不错,我们可以创建一个新的更大的数组并逐个复制值,这有点慢。它的技术背景是什么? 问题答案: 这个问题没有提到语言,因此我将选择基于“ C”的数组作为答案。 数组被分配为单个内存块。增长数组是有问题的,因为正确执行此操作的唯一方法是在最后增长它。为了增加大小N,在数组的末尾必须在下一个分配的地址之前至少有N个空闲字节。 要支持这种类型

  • 问题内容: 在Java 5及更高版本中,您具有foreach循环,该循环可以神奇地实现任何实现的对象: 但是,仍然没有实现,这意味着要迭代一个,您必须执行以下操作: 有谁知道为什么仍然不执行? 编辑: 为澄清起见,我不是在谈论枚举的语言概念,而是在Java API中称为“ 枚举 ” 的Java特定类。 问题答案: 枚举没有被修改为支持Iterable,因为它是一个接口,而不是一个具体的类(例如Ve