Object 有关对象的目的、使用和查询。比较实用程序方法
我有一个关于使用新对象的问题。compare(o1,o2,Comparator)方法-根据我自己的测试,如果o1和o2都为null,那么它返回0,但是,如果其中一个为null,那么它仍然抛出null指针异常。我在Objects.equals和其他一些Objects实用程序方法上找到了很多资料,但在Objects.compare和何时使用它/用它替换旧代码方面没有太多资料 所以在这里我可以这样做:Object 有关对象的目的、使用和查询。比较实用程序方法,object,null,compare,java-8,comparator,Object,Null,Compare,Java 8,Comparator,我有一个关于使用新对象的问题。compare(o1,o2,Comparator)方法-根据我自己的测试,如果o1和o2都为null,那么它返回0,但是,如果其中一个为null,那么它仍然抛出null指针异常。我在Objects.equals和其他一些Objects实用程序方法上找到了很多资料,但在Objects.compare和何时使用它/用它替换旧代码方面没有太多资料 所以在这里我可以这样做: String s1 = "hi"; String s2 = "hi"; int x = Object
String s1 = "hi";
String s2 = "hi";
int x = Objects.compare(s1, s2, Comparator.naturalOrder());
System.out.println("x = " + x);
很好,返回0,现在是:
String s1 = null;
String s2 = null;
也可以正常工作并返回0。然而,这:
String s1 = "hi";
Strng s2 = null;
抛出NullPointerException。我猜Object.compare(o1,o2,Comparator)和o1.compareTo(o2)的好处在于它至少可以处理两个对象都为null的情况,当其中一个为null时,它允许您设计一个比较器来处理它。我猜想,例如
int x = Objects.compare(s1, s2, Comparator.nullsFirst(Comparator.naturalOrder()));
而对于x.compareTo(y),除非您事先这样做,否则无法处理null?那么Java库开发人员现在是否打算让我们用Objects.compare替换所有对compareTo的调用,而我们关心的是空值?e、 g.我们会在类似的实施中这样做吗
侧边查询1:关于使用nullsFirst,如果使用它,然后传入一个比较器,该比较器使用比较、然后比较等链接,它是否适用于所有内部比较器?e、 g
Comparator.nullsFirst(Comparator.comparing(Song::getTitle)
.thenComparing(Song::getArtist)
.thenComparing(Song::getDuration)
)
这会将nullsFirst应用于内部的所有内容,还是需要对每个内容单独使用nullsFirst?通过测试,我认为它只适用于实际的歌曲对象为null,而不适用于标题或艺术家为null的字段,也就是说,如果它们为null,那么仍然会抛出NullPointerException。不管怎么说
旁白2:最后一个问题是,因为我喜欢Comparator.Comparating语法,我建议开始用它来编写compareTo实现——我一直在努力思考如何取代这种传统方法,例如
public int compareTo(Song other) {
int result = this.title.compareTo(other.title);
if (result == 0) {
result = this.artist.compareTo(other.artist);
if (result == 0) {
result = Integer.compare(this.duration, other.duration);
}
}
return result;
}
然后我想我可以使用对象。比较(…)如下:
public int compareTo(Song other) {
return Objects.compare(this, other, Comparator.nullsFirst(
Comparator.comparing(Song::getTitle)
.thenComparing(Song::getArtist)
.thenComparingInt(Song::getDuration)
));
}
我认为这个版本更优雅-我假设它是按照我认为的那样工作的,例如,通过将这个和其他作为前两个参数传递给比较器,然后传递给比较器,它与使用if语句的传统比较方法具有相同的效果?虽然我可以看到Objects.compare捕获两个null的好处永远不会出现,就好像这是null一样,但是永远不会到达compareTo方法调用(通过处理异常或抛出异常)。但是通过使用nullsFirst,我想如果传入的参数,即other,为null,那么这将安全地处理这个问题
非常感谢您的帮助。
对象。compare
并不意味着提供null
安全比较,因为没有可以实现的默认行为。它只是实现了一个快捷方式,当两个对象相同时,不调用比较器的方法。换句话说,它确实a==b?0:c.比较(a,b)
,仅此而已。因此,当两个对象都null
时不中断只是一个副作用。封装的代码可能看起来微不足道,但此类中的其他方法属于类似的类别。大量使用小型实用方法仍可能带来显著的胜利
顺便说一下,它根本不是Java8方法。它从Java7开始就存在
关于你的第二个问题,Comparator.nullsFirst(…)
修饰现有的比较器
,并将在委托给提供的比较器之前强制执行null
值的规则,因为该比较器的目的是保护现有比较器永远看不到null
值。装饰后的比较器是否是链式比较器并不重要。只要它是你所谓的“内部比较器”,就像
您不能对nullsFirst
的结果调用然后比较
,因为这意味着在两个值都为null
时调用下一个比较器
Comparator.nullsFirst(Comparator.comparing(a).thenComparing(b)) // perfect
Comparator.nullsFirst(Comparator.comparing(a)).thenComparing(b) // ouch
现在转到第三个问题,使用nullsFirst
比较器实现compareTo
方法违反了以下规则:
实施者必须确保所有x
和y
的sgn(x.compareTo(y))==-sgn(y.compareTo(x))
。(这意味着x.compareTo(y)
必须在y.compareTo(x)
引发异常时引发异常。)
这意味着将null
作为参数传递应该总是导致NullPointerException
作为交换参数,接收方也会无条件地抛出
包含null
策略的订单应始终作为单独的比较器提供
请注意,这也会非常低效,因为您会为每个比较调用创建一个新的比较器
(准确地说是多个比较器
)。现在,对这些对象的一个相当大的列表进行图像排序…对象。compare
并不意味着提供一个null
安全的比较,因为没有可以实现的默认行为。它只是实现了一个快捷方式,当两个对象相同时,不调用比较器的方法。换句话说,它确实a==b?0:c.比较(a,b)
,仅此而已。因此,当两个对象都null
时不中断只是一个副作用。封装的代码可能看起来微不足道,但此类中的其他方法属于类似的类别。大量使用小型实用方法仍可能带来显著的胜利
顺便说一下,它根本不是Java8方法。它从Java7开始就存在
关于您的第二个问题,Comparator.nullsFirst(…)
修饰现有的比较器
,并将在委托给提供的比较器之前强制执行null
值的规则,因为此比较器的目的是保护现有比较器不受
public static final Comparator<Song> COMP_DEFAULT
= nullsFirst(comparing(Song::getTitle, nullsFirst(naturalOrder()))
.thenComparing(Song::getArtist, nullsFirst(naturalOrder()))
.thenComparingInt(Song::getDuration));
public int compareTo(Song other) {
return COMP_DEFAULT.compare(this, other);
}