在不少涉及到排序的 Api 中,都会提到自然排序或者字段排序,那么怎么定义自然排序和字典排序呢?特别是涉及到中文的时候,自然排序到底按什么排序呢?本文将会和大家一起一探究竟。
文档中是这么描述的 sort 方法的:
Sorts the specified list into ascending order, according to the natural ordering of its elements.All elements in the list must implement the Comparable interface ...
natural ordering 翻译成中文便是自然排序。
注意:下文中 Collections.sort 如无特殊说明,都是特指该签名的方法,因为 Collections 还包含一个不同签名的 sort 方法。
A Red-Black tree based NavigableMap implementation. The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.
在构造 TreeMap 的时候,如果不指定 Comparator,TreeMap 会对 key 进行自然排序。使用自然的排序的例子还有很多,我们就到此为止了。
提到自然排序,我们第一反应就是阿拉伯数字从小到大排序,然后就是英文字母按照 abcde ... 的顺序排序。好像自然排序是很容易理解的一个概念。但是仔细一想就不是那么回事了!
前面提到的 Collections.sort 方法是一个泛型方法,自然可以接收任何类型的 list。让我们来排序中文看看是什么结果。
这个地方自然排序到底按照什么排序呢?按照拼音顺序吗?从上面的输出结果可以很容易看出答案是否定的。从输出结果来看完全没规律。在解开谜底之前,让我们先来尝试排序一个自定义的对象。
这段代码,编译就会报错,因为 Collections.sort 要求 List 中元素的类型必须实现 Comparable 接口。问题到这里基本上清楚了,所谓的自然排序就是要求参与排序的元素所属类必须实现 Comparable 接口。由 Comparable 接口中的 compareTo 方法来决定排序的规则。
好巧不巧,Integer 中的 compareTo 方法正是按照数字大小从小到大排序的,这和我们从小理解的自然排序是一致的。
更巧合的是纯英文字符串恰好就是按照字典顺序排序的,然而对于中文就不灵了。那么问题来了中文的自然排序到底是怎么排序的呢?
要搞清楚这个问题,只需要看看 String 中的 compareTo 方法究竟是怎么排序不就可以了吗?以下代码来自 java8,虽然从 Java9 开始正式引入了 Compact Strings,但是不影响问题的理解。
不论是中文还是英文,字符串的比较,实际比较的是字符串内部的 char 数组,而 char 是采用 utf-16 编码的。现在让我们再来理解下 testNaturalOrder 为什么输出 。
从 https://www.compart.com/en/unicode 可以查到“自然排序”这几个字的 utf-16 编码的值分别为 0x81EA、0x7136、0x6392 和 0x5E8F。比较这几个编码值的大小就可以得出输出结果为 。
从这里可以看出,中文的自然排序和拼音没有任何关系,中文的自然排序也没什么实际意义。如果要想中文按照拼音排序,可以使用 Collections 中另一个 sort 方法,该方法允许指定一个 Comparator。通过 Comparator 可以自定义任何排序规则。
Java 实现中自然排序并非我们从小理解的自然排序,自然排序是由排序对象所属类实现的 compareTo 方法决定的。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/java-jiao-cheng/14766.html