简体   繁体   English

当参数字符串为 null 时,int compareTo() 应该返回什么?

[英]What should int compareTo() return when the parameter string is null?

It is said that when input parameter is null, compareTo() should throw a NullPointerException.据说当输入参数为null时,compareTo()应该抛出NullPointerException。 However, I am implementing a class which needs to compare fields with the type of String.但是,我正在实现一个 class ,它需要将字段与字符串类型进行比较。 These fields need not to be mandatory.这些字段不必是强制性的。 I wonder in this case,我想知道在这种情况下,

1) What should I return when the input is null? 1)当输入为null时我应该返回什么? Should any not-null strings lexicographically bigger or smaller than null?任何非空字符串在字典上是否应该大于或小于 null?

and

2) If this is considered bad practice, is there any supporting arguments? 2)如果这被认为是不好的做法,是否有任何支持 arguments? Should I force the user to use empty strings instead?我应该强制用户使用空字符串吗? If using empty string, won't that confuse the case in which the field is not applicable and the case in which the field is empty?如果使用空字符串,会不会混淆字段不适用和字段为空的情况? And if exception must be thrown, then except from warning the user in the manual, what else could/shall I do?如果必须抛出异常,那么除了在手册中警告用户之外,我还能/应该做什么?

EDIT: I might not express myself clearly here, but in the program I am implementing, the strings that could be null are all fields or a class, which should not be null.编辑:我可能在这里没有清楚地表达自己,但在我正在实施的程序中,可能是 null 的字符串都是字段或 class,不应该是 null。 In other words, the objects comparedTo() uses could not be null, just their private fields could be.换句话说,comparedTo() 使用的对象不能是 null,只能是它们的私有字段。 So in this case, I believe if I implement compareTo() properly, it would not violate the transitive requirement since classes with null fields would be considered the same always.所以在这种情况下,我相信如果我正确地实现 compareTo(),它不会违反传递性要求,因为具有 null 字段的类总是被认为是相同的。 Am I right or am I interpreting this wrong?我是对的还是我解释错了?

Thank you all for the answers!谢谢大家的回答!

From javadoc for Comparable来自 javadoc 的Comparable

Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.请注意,null 不是任何 class 的实例,即使 e.equals(null) 返回 false,e.compareTo(null) 也应该抛出 NullPointerException。

Yes, there is no problem allowing null for instance fields - just make sure its sorting order is defined.是的,允许null作为实例字段没有问题 - 只需确保定义了其排序顺序。 Most natural would be putting it either before or after all real strings, but you could do anything here, just do it consistently.最自然的是将它放在所有真实字符串之前或之后,但是您可以在这里做任何事情,只要始终如一地做。 (For example, you could sort null like "null" .) (例如,您可以将null排序为"null" 。)

Here is an example implementation for a single member:这是单个成员的示例实现:

class Example implements Comparable<Example> {

   @Nullable
   private String member;

   // TODO: getter, setter, constructor, ...

   public int compareTo(Example that) {
      if(this.member == null)
         if(that.member == null)
            return 0; //equal
         else
            return -1; // null is before other strings
       else // this.member != null
         if(that.member == null)
            return 1;  // all other strings are after null
         else
            return this.member.compareTo(that.member);
   }
}

Please note that the specification of Comparable.compareTo() only has a constraint for o.compareTo(null) (which should behave just like - null.compareTo(o) , ie throw a NullPointerException), but not about how null fields are handled (it doesn't mention fields at all, so a class could return whatever it wants, as long as the antisymmetry, reflexivity and transitivity is ensured).请注意,Comparable.compareTo() 的规范仅对o.compareTo(null)有约束(其行为应类似于- null.compareTo(o) ,即抛出 NullPointerException),但与如何处理null字段无关(它根本没有提到字段,所以只要保证反对称、自反性和传递性,class 就可以返回它想要的任何东西)。

It would be a bad practice to not throw an exception because it violates the transitive antisymmetric nature of compareTo.不抛出异常是一种不好的做法,因为它违反了 compareTo 的 传递 反对称性质。

From Comparable.compareTo documentation:Comparable.compareTo文档:

The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.实现者必须确保所有 x 和 y 的 sgn(x.compareTo(y)) == -sgn(y.compareTo(x))。 (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.) (这意味着如果 y.compareTo(x) 抛出异常,则 x.compareTo(y) 必须抛出异常。)

The implementor must also ensure that the relation is transitive: (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.实现者还必须确保关系是可传递的:(x.compareTo(y)>0 && y.compareTo(z)>0) 意味着 x.compareTo(z)>0。

Finally, the implementor must ensure that x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.最后,实现者必须确保 x.compareTo(y)==0 意味着 sgn(x.compareTo(z)) == sgn(y.compareTo(z)),对于所有 z。

More importantly, it's a bad idea to use compareTo on your objects to compare them with strings, for the same reason: sign(obj.compareTo(str)).= -sign(str.compareTo(obj)) .更重要的是,出于同样的原因,在对象上使用 compareTo 将它们与字符串进行比较是一个坏主意: sign(obj.compareTo(str)).= -sign(str.compareTo(obj)) Implement a custom Comparator and do whatever you want in it.实现一个自定义比较器并在其中做任何你想做的事情。

Because the documentation of compareTo states that it should throw a NullPointerException , you should follow those guidelines so your implementation is consistent with the interface documentation.因为compareTo的文档声明它应该抛出NullPointerException ,所以您应该遵循这些准则,以便您的实现与接口文档一致。 This also handles the questions of whether or not non-null strings are lexicographically smaller or bigger than null .这也处理了非空字符串在字典上是否小于或大于null的问题。

You have a couple of options on how to handle this.你有几个关于如何处理这个问题的选择。 If empty and not-applicable are different, then you should probably wrap the string field in your own field class.如果空和不适用不同,那么您应该将字符串字段包装在您自己的字段 class 中。 For example, say you could create a type of MyField that might have an isApplicable method, which indicates if the field is applicable to this case (or something similar).例如,假设您可以创建一种可能具有isApplicable方法的 MyField 类型,该方法指示该字段是否适用于这种情况(或类似的东西)。 Or you could rethink your design and be sure that an empty string and N/A really are two different things.或者您可以重新考虑您的设计,并确保空字符串和 N/A 确实是两个不同的东西。 If they are, you do need a way to differentiate between the two.如果是,您确实需要一种方法来区分两者。

You need to decide if null is greater-than or less-than to a non-null value.您需要确定 null 是大于还是小于非空值。 You can design compareTo to meets the needs of your class's natural ordering, thus it is not bad practice.你可以设计compareTo来满足你的类自然排序的需要,因此这是一个不错的做法。

In addition to Paulo Ebermann 's accepted answer, if you need to handle ASC/DESC order, you would do this.除了Paulo Ebermann接受的答案之外,如果您需要处理ASC/DESC订单,您会这样做。 (We're assuming that NULLs always come before Non-NULLs in normal ascending order, otherwise for descending.) (我们假设 NULL 总是按正常升序排列在 Non-NULLs 之前,否则按降序排列。)

    final boolean sortAsc = false; // Suppose this TRUE/FALSE is for ASC/DESC
    
    objects.sort(new Comparator<Example>() {

        @Override
        public int compare(Example e1, Example e2) {

            if (e1.getMember() == null && e2.getMember() == null) {
                return 0; // Both NULLs are equal
            }
            else if (e1.getMember() == null && e2.getMember() != null) {
                return sortAsc ? -1 : 1; // NULLs should precede non-NULLs in ascending order, follow in descending order
            }
            else if (e1.getMember() != null && e2.getMember() == null) {
                return sortAsc ? 1 : -1; // Non-NULLs should follow NULLs in ascending order, precede in descending order
            } else {
                // Both non-NULLs
                return sortAsc ? e1.getMember().compareTo(e2.getMember()) 
                               : e2.getMember().compareTo(e1.getMember());
            }
        }
        
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 String 类 compareTo() 方法返回什么 - What does the String classes compareTo() method return java,如果参数为null,则字符串方法应返回null,但它会抛出NullPointerException - java, a string method should return null if the parameter is null but it throws NullPointerException 如果参数是同一接口的不同实现,则compareTo()应该返回什么? - What should compareTo() return if argument is different implementation of the same interface? Java-修改后的compareTo方法表示需要返回一个int,但应该返回一个int - Java - modified compareTo method says it needs to return an int, but it should be returning one compareTo() 实际上返回什么? - What does compareTo() actually return? Java compareTo方法。 student.compareTo方法应返回 - Java compareTo method. The student.compareTo method should return 如何解决无法调用“String.compareTo(String)”,因为“<parameter1> [<local3> ]”是 null?</local3></parameter1> - How to solve Cannot invoke “String.compareTo(String)” because “<parameter1>[<local3>]” is null? 未记载的String.compareTo(null)NPE? - Undocumented String.compareTo(null) NPE? Java中的compareTo方法返回什么 - What does compareTo method return in java 为什么compareTo在应该为false时返回true? - why is compareTo returning true when it should be false?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM