自然排序和全序排序的区别

47
我偶然看到很多这样的陈述,例如,在对数组或集合进行排序时需要自然排序时使用“comparable”,而需要完全排序时则使用“comparator”。
你所听到的版本可能相同或不同,但最终这是区分两种接口(comparator和comparable)之间差异的其中一个因素。
但是,我在任何地方都找不到这两种排序方式之间的区别。如果有人能用一个好的例子来解释一下,我会非常感激 :)
8个回答

35

总排序意味着所有值都可以相互比较。例如,如果您有一个包含BigDecimalString的集合,则没有自然的总排序(但您可以发明一个)

在Java中,自然顺序被定义为JVM提供的顺序。这可能与人们认为的自然顺序不同。例如,字符串按照ASCII字符顺序排序。这意味着大写字母Z在小写字母a之前,而数字102之前。

http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html

此接口对实现它的每个类的对象强制执行总排序。此排序称为类的自然排序,并且类的compareTo方法称为其自然比较方法。


2
你所说的“所有值都可以与其他所有值进行比较”,具体是什么意思?你能详细解释一下吗? - AnV
1
@AbhinavVutukuri 在集合中,你可以说有些是可比的,而其他一些则不是。所有值都必须与其他每个值可比。 - Peter Lawrey
1
@PeterLawrey 请问在字符串排序时,为什么 z 要排在 a 前面?您能确认这是准确的吗?https://gist.github.com/kmb385demo/d580f0c47b359eba9b41b6e35293d2ce - Kevin Bowersox
@KevinBowersox 在Java中大小写是有区别的。大写字母Z在小写字母a之前。https://ideone.com/fXjyo8 - Peter Lawrey
3
@PeterLawrey,是时候提高显示器的分辨率了(换行也没有帮助)。我原以为那是一个小写字母 z,就像你从我的例子中看到的那样。谢谢你指出来,你让我开始怀疑我所学习的一切!我为老年开发者做了一个快速修改,以帮助他们变得更加清晰易见。 - Kevin Bowersox

11
为了解释@Bruno的答案,举一个部分排序的例子是正数之间的整除关系。如果你比较5和15,可以说5是15的约数,而15是5的倍数。但是,3和5不可比较,因为3既不是5的约数也不是5的倍数。
一个完全排序的例子是小于关系,因为如果你取任意两个不同的数字,其中一个一定小于另一个。所以任何值都可以与任何其他值进行比较。
关于“自然排序”的概念:如果某种类型的对象有一种非常明显的排序方式,那么它就是自然排序。例如,字符串的自然排序是按字母顺序排列,数字的自然排序是按升序排列,因为这是任何人都会想到的第一选择。然而,有时您可能希望以不同的方式对字符串进行排序,例如按长度从1个字符的字符串开始排序到更长的字符串。这是字符串上的一种可能的完全排序,但不是自然排序。
并非所有对象都必须具有自然排序。例如,如果您有Person对象,则按身高对其进行排序是一种可能的完全排序,但按年龄对其进行排序也是一种可能的完全排序。没有一个比另一个更明显,这就是为什么没有自然排序的原因。

10

自然顺序

它取决于我们使用的集合,例如,假设我们有一个字符对象,那么自然顺序是它们的Unicode值,对于数字,自然顺序是通常的升序。

Comparable接口- 该接口对实现它的每个类的对象强制执行总排序。这种排序称为类的自然排序,而类的compareTo方法称为其自然比较方法。

实现此接口的对象的列表(和数组)可以通过Collections.sort(和Arrays.sort)自动排序。实现此接口的对象可以用作已排序映射中的键或已排序集合中的元素,无需指定比较器。

public interface Comparable<T> {

    /**
     * Compares this object with the specified object for order.  Returns a
     * negative integer, zero, or a positive integer as this object is less
     * than, equal to, or greater than the specified object.
     */
    public int compareTo(T o);
}

比较器接口:

该接口表示一种排序关系,可用于对列表进行排序或在有序集合或映射中维护顺序。可以重写类型的自然排序,或者对不实现Comparable接口的类型的对象进行排序。

比较函数会对“某些对象集合”实施完全排序。比较器可传递给排序方法(如Collections.sort)以允许精确控制排序顺序。比较器还可用于控制某些数据结构(如TreeSet或TreeMap)的顺序。

    public interface Comparator<T> {
    /**
     * Compares its two arguments for order.  Returns a negative integer,
     * zero, or a positive integer as the first argument is less than, equal
     * to, or greater than the second.
     */
    int compare(T o1, T o2);

    boolean equals(Object obj);
}

Hope This helps you.                    

10

全序关系是一个通用的数学概念。它与偏序关系的主要区别在于,对于集合X中的每个元素a和b,要么“a <= b”成立,要么“b <= a”成立。就Java而言,这意味着在两个Comparable实例中,必须有一个大于或等于另一个(即比较它们是有意义的)。


9

重要提示: 自然排序 应该与相等关系一致

总结: 自然排序是一种全序,它是给定类的默认排序方式,并且与相等关系一致。全序是任何值都可以与其他所有值进行比较的排序方式。

例如: 当您设计新类时,可以选择在该类内部使用自然排序。其他任何排序方式都必须是全序的 ;)


1
你所说的“所有值都可以与其他所有值进行比较”,具体是什么意思?你能详细解释一下吗? - AnV

4
自然排序是一种默认的全序。这是两者之间唯一的区别。

2
这就是我没有理解的地方。对我来说就像一个谜一样。您能否请解释一下默认排序是什么意思? - Nav
我知道,但是就像我说的那样,当你说“自然”的时候,它的意思对我来说有点模糊,不太容易理解。 :( - Nav
当您定义对象时,可以选择在没有提供其他排序方式时使用的排序方式。因此,通常会实现在实践中最常用的排序方式。 - Ha.
@Ha. 但是什么是全序 - AnV
@AnV - 假设你有一个名为“Student”的类,那么基于“Student”类的多个/不同元素对学生集合进行排序称为总排序。 - krohit

2

0
简单回答:Java中没有自然顺序。
如果一个类(像许多类一样)实现了java.util.Comparable接口,那么compareTo方法定义了实例的顺序,我们可以使用例如java.util.Arrays.sort进行排序。如果类没有提供compareTo方法,那么顺序是未定义的,并且java.util.Arrays.sort会导致运行时java.lang.ClassCastException异常:"...无法转换为java.lang.Comparable"。 因为几乎所有类都实现了java.util.Comparable接口,所以这似乎是它们的自然顺序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接