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

Java8和方法参考-具体比较ToIgnoreCase

巫研
2023-03-14

我阅读了关于Lambda表达式的Java 8教程,但不太了解“引用特定类型的任意对象的实例方法”的方法引用示例

在同一教程中,有一个示例“引用特定对象的实例方法”,看起来像。

public int compareByName(Person a, Person b) {
        return a.getName().compareTo(b.getName());
}
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);

我可以看到这个工作,因为方法compareByName与Comparator.comparelambda(a, b)具有相同的签名-

现在“引用特定类型的任意对象的实例方法”示例使用String::compareToIgnoreCase

String[] stringArray = { "Barbara", "James", "Mary", "John",
    "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);

该方法的签名是int compareTo(String anotherString),与Comparator不同。比较本教程不太清楚,但似乎暗示您最终会得到一个lambda,如(a,b)-

public class LambdaTest {

    public static void main(String... args) {
        String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };

        Arrays.sort(stringArray, String::compareToIgnoreCase);      // This works

        // using Static methods
        Arrays.sort(stringArray, FakeString::compare);              // This compiles
        Arrays.sort(stringArray, FakeString::compareToIgnoreCase);  // This does not

        // using Instance methods
        LambdaTest lt = new LambdaTest();
        FakeString2 fs2 = lt.new FakeString2();
        Arrays.sort(stringArray, fs2::compare);                 // This compiles
        Arrays.sort(stringArray, fs2::compareToIgnoreCase);     // This does not

        for(String name : stringArray){
            System.out.println(name);
        }
    }

    static class FakeString {
         public static int compareToIgnoreCase(String a) {
             return 0;
         }


        public static int compare(String a, String b) {
            return String.CASE_INSENSITIVE_ORDER.compare(a, b);
        }
    }

    class FakeString2 implements Comparator<String> {
         public int compareToIgnoreCase(String a) {
             return 0;
         }

        @Override
        public int compare(String a, String b) {
            return String.CASE_INSENSITIVE_ORDER.compare(a, b);
        }
   }
}

有人能解释一下为什么上面两个数组。sort不编译,即使它们使用的方法与String相同。比较IgnoreCase方法

共有2个答案

谷梁宏恺
2023-03-14

在FakeString中,您的compareToIgnoreCase有一个字符串参数,因此它不能代替比较器

在FakeString 2中,您的compareToIgnoreCase有一个隐式FakeString参数(this)和一个字符串参数,因此它同样不能代替Comparator

贝浩歌
2023-03-14

这是某个对象上的方法引用和正在处理的对象上的方法引用之间的区别。

首先是Oracle示例

让我们看看第一种情况:

public int compareByName(Person a, Person b) {
        return a.getName().compareTo(b.getName());
}
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);

这里,对传入的myComparisonProvider实例调用方法compareByName,并使用排序算法中的每对参数。

所以在这里,当比较ab时,我们实际上调用:

final int c = myComparisonProvider.compareByName(a,b);

现在,在第二种情况下:

String[] stringArray = { "Barbara", "James", "Mary", "John",
    "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);

您正在排序一个字符串[],因此将对当前正在排序的字符串实例调用方法compareToIgnoreCase,并将另一个字符串作为参数进行排序。

所以在这里,当比较ab时,我们实际上调用:

final int c = a.compareToIgnoreCase(b);

这是两种不同的情况:

  • 一种在任意对象实例上传入方法的方法;和

在您的示例

现在,在第一个示例中,您还有一个字符串[],并尝试对其进行排序。因此:

Arrays.sort(stringArray, FakeString::compare);

所以在这里,当比较ab时,我们实际上调用:

final int c = FakeString.compare(a, b);

唯一的区别是比较是静态的。

Arrays.sort(stringArray, FakeString::compareToIgnoreCase);

现在,String[]不是FakeString[],因此我们不能在String上调用此方法。因此,我们必须在FakeString上调用静态方法。但我们也不能这样做,因为我们需要一个方法(String, String)-

在第二个示例中,问题完全相同,因为您仍然有一个String[]。和compareToIgnoreCase有错误的签名。

您缺少的一点是,在示例中;对当前正在处理的字符串调用该方法。

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

  • 假设我有一个双人课 我希望对它进行排序,首先是第一个值,然后是第二个值。现在,如果我这样做 一切都很好,列表按对的第一个值排序,但如果我这样做 它因错误而失败 好吧,所以它可能无法推断参数,所以如果我这样做 它因错误而失败 为什么它适用于comparing()而不适用于comparing()。然后比较()?

  • 我想用Lambda对列表排序: 但我得到了这个编译错误:

  • 我有一个类字段,和。我需要使用对它们进行排序,但我得到了一个异常: java.lang.IllegalArgumentException:比较方法违反了它的一般约定! 我的< code>compareTo方法: 请帮我找出compareTo方法中的错误。谢了。

  • 我正在做一个关于java类的介绍的作业,该作业要求使用方法将温度从摄氏转换为华氏,反之亦然。它需要使用三种比较方法,而我无法弄清楚该把什么放进去。以下是说明: 三种比较方法: -此方法将另一个温度作为参数,如果调用对象具有与other相同的温度,则返回true,否则返回false。注意,摄氏温度可以等于华氏温度,如上式所示。 -如果调用对象的温度低于其他温度,则此方法将返回true,否则返回fal

  • 我需要一种标准方法来比较JPA实体与其DTO并确定它们是否代表相同的业务对象。我可以想到三种方法,每个DTO上的自定义方法,带有静态方法的接口或比较器。 基于若昂·迪亚斯的回答,方法4-继承。 优点/缺点 方法1-一路坏 方法2-使用接口支持组合而不是继承,但需要使用自定义方法名称的语义学() 方法3-不需要修改源代码 方法4-简化语义学,因为它使用标准但需要“样板 这些方法的任何其他优缺点或对其