当前位置: 首页 > 知识库问答 >
问题:

Java 8 Lambdas max()在流中使用Integer.max作为比较器[重复]

冯文彬
2023-03-14

我用示例值编写了简单的<code>列表,但事实证明,我也可以传递<code>Integer::max

此外,程序打印出奇怪的结果,我检查了它的“内部”,它看起来没问题,但在我得到最终结果后-它们不准确。

例子:

@Test
public void testHowIntegerMaxWorksInStream() {
    List<Integer> list = Arrays.asList(5,3,8);
    Optional<Integer> op = list.stream().max((a, b) -> {
        System.out.println("Input arguments a=" + a + ", b=" + b);

        int max = Integer.max(a, b);
        System.out.println("Returning max(a,b)=" + max);
        return max;
    });
    System.out.println("Optional result=" + op.get());
}

输出:

Input arguments a=5, b=3
Returning max(a,b)=5
Input arguments a=5, b=8
Returning max(a,b)=8 // OK, Integer::max got 8.. but then ...
Optional result=5 // .. I got 5. WHY ???

我的问题是:

  1. 为什么我可以传递整数::max来代替比较器
  2. 为什么我的函数返回5作为结果,而在内部它是8

共有3个答案

姚培
2023-03-14

因为您创建的比较器总是返回第一个最大的元素。

如果您比较AB,如果A较小,则应返回-1。您返回ABInteger.max,在您的情况下,它始终是

(a,b) -> { 
   if (a>b) return 1;     // <-- you return a positive value always, so stream.max() thinks 5>8 :)
   if (a<b) return -1;
   if (a==b) return 0;
}

劳和歌
2023-03-14

遗憾的是,< code>Integer.max代替比较器进行编译的原因是,它的返回类型符合stream的< code>max方法的预期:比较的结果是一个< code>int,比较两个< code>int的结果也是一个< code>int。但是,< code>Integer.max返回的结果与stream的< code>max预期的结果不一致,这解释了不正确的结果:例如,如果将< code>(5,8)传递给< code>Integer.max,它将返回< code>8,一个正数;然而,stream的< code>max将所有正数解释为第一个参数大于第二个参数的指示,这在这种情况下是不正确的。

此编译的唯一原因是您的比较器返回一个int。这不适用于DoubleBigIntger

南宫泓
2023-03-14

你误会了。< code>max(comparator)采用比较整数的比较器。你所做的不是比较整数,即判断< code>a是否大于< code>b。你拿走了它们中的最大值,然后还回去。所以你说< code>a总是大于< code>b,因为你总是返回一个正数(你的列表只包含正数)。< code >比较器返回:

作为第一个参数的负整数、零或正整数小于、等于或大于第二个参数。

你需要做的是

public void testHowIntegerMaxWorksInStream() {
    List<Integer> list = Arrays.asList(5,3,8);
    Optional<Integer> op = list.stream().max((a, b) -> {
        int compare = Integer.compare(a, b);
        return compare;
    });
    System.out.println("Optional result=" + op.get());
}

即调用整数比较而不是最大值,这恰恰是这样做的:

比较其两个参数的顺序。当第一个参数小于、等于或大于第二个参数时,返回负整数、零或正整数。

对于问题的第二部分,请参阅::(双冒号)运算符在Java 8中。它被称为方法引用。所以另一种写法是:

List<Integer> list = Arrays.asList(5,3,8);
Optional<Integer> op = list.stream().max(Integer::compare);
System.out.println("Optional result=" + op.get());
 类似资料:
  • 我试图编写一个接受两个参数的函数,和。然后,它应该按照中给出的顺序对进行排序。例如,如果是,是,则函数应返回,排序中的顺序元素。 我按照下面的方式编写代码,但在arrays.sort处不断出现错误。我想我没有正确地使用lambda。你能具体说明我做错了什么吗?

  • 我是一名自学型开发人员,现在正在学习Java。我了解到,要对函数接口使用方法引用,我们引用的方法的签名必须与该函数接口内抽象方法的签名匹配。 但是在学习比较器时,发现“Comparator.comparing()”方法接受函数接口并返回一个比较器。我知道函数接口的抽象方法必须接受一个参数并返回一个值。 但是我可以将任何部分(而不是完全)匹配Function接口签名的方法(作为方法参考)传递给比较器

  • 日安- 我正在处理一个任务,在该任务中,我有指令来创建一个名为的方法,该方法将执行以下任务: public int compare(Object first,Object second)(请注意,您还可以定义:public int compare(Attory first,Attory second),方法是让类 为此,我创建了一个类,如下所示: AthletenameComparator

  • 我有一个关于compareTo函数如何帮助比较器排序的问题,即o1。比较(o2)与o2。比较(o1) 如果两个字符串相等,则此方法返回0,否则返回正值或负值。如果第一个字符串在词典上大于第二个字符串,则结果为正,否则结果为负。 上面的陈述很简单,但是为什么o1.compare(o2)会给我一个升序,而o2.compare(o1)给了我一个降序? 如果我有整数值“5,10,3”,我得到3,5,10和

  • 问题内容: 无论如何,要使下面的代码仍然使用开关,而不返回它,是吗?谢谢! 当然,如果使用if语句,您将像这样: 但是对于更复杂的示例,这变得很冗长。 问题答案: 抱歉,根据switch()文档 ,您不能在switch语句中使用比较: 请注意,开关/外壳确实比较松散。 这意味着您必须提出解决方法。从松散的比较表 ,你可以利用的事实是类型转换错误:

  • 多种多样的工作流使得在项目中实施 Git 时变得难以选择。这份教程提供了一个出发点,调查企业团队最常见的 Git 工作流。 阅读的时候,请记住工作流应该是一种规范而不是金科玉律。我们希望向你展示所有工作流,让你融会贯通,因地制宜。 这份教程讨论了下面四种工作流: 中心化的工作流 基于功能分支的工作流 Gitflow工作流 Fork工作流 中心化的工作流 过渡到分布式分版本控制系统看起来是个令人恐惧