java集合架構針對不同的資料結構提供了多種排序的方法,
雖然很多時候我們可以自己實作排序,比如數組等,但是靈活的使用jdk提供的排序方法,可以提高開發效率,而且通常jdk的實作要比自己造的輪子性能更優化。
java api對arrays類的說明是:此類包含用來操作數組(比如排序和搜尋)的各種方法。
(1)使用arrays排序
arrays使用非常簡單,直接調用sort()即可:
1
2
3
4
5
6
7
8
9
10
11
<code>int</code><code>[] arr = </code><code>new</code> <code>int</code><code>[] {</code><code>5</code><code>,</code><code>8</code><code>,-</code><code>2</code><code>,</code><code>0</code><code>,</code><code>10</code><code>};</code>
<code> </code><code>arrays.sort(arr);</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>i=</code><code>0</code><code>;i<arr.length;i++){</code>
<code> </code><code>system.out.print(arr[i]+</code><code>","</code><code>);</code>
<code> </code><code>}</code>
<code> </code>
<code> </code><code>char</code><code>[] chararr = </code><code>new</code> <code>char</code><code>[] {</code><code>'b'</code><code>,</code><code>'a'</code><code>,</code><code>'c'</code><code>,</code><code>'d'</code><code>,</code><code>'d'</code><code>};</code>
<code> </code><code>arrays.sort(chararr);</code>
<code> </code><code>system.out.print(chararr[i]+</code><code>","</code><code>);</code>
如果需要降序排序, 升序排序後逆序即可:
<code>collections.reverse(arrays.aslist(arr)); </code>
(2)arrays.sort()的實作
檢視源碼會發現,arrays.sort()有許多重載的方法,如sort(int[] a)、sort(long[] a) 、sort(char[] a)等,
<code>public</code> <code>static</code> <code>void</code> <code>sort(</code><code>int</code><code>[] a) {</code>
<code> </code><code>dualpivotquicksort.sort(a);</code>
<code> </code><code>}</code>
但最終都是調用了dualpivotquicksort.sort(a)的方法,
這是一個改進的快速排序,采用多路快速排序法,比單路快速排序法有更好的性能,
并且根據數組長度不同會最終選擇不同的排序實作,
看一下這個方法的實作,這裡不作展開:
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<code>public</code> <code>static</code> <code>void</code> <code>sort(</code><code>char</code><code>[] a) {</code>
<code> </code><code>sort(a, </code><code>0</code><code>, a.length - </code><code>1</code><code>);</code>
<code> </code><code>}</code>
<code> </code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>sort(</code><code>char</code><code>[] a, </code><code>int</code> <code>left, </code><code>int</code> <code>right) {</code>
<code> </code><code>// use counting sort on large arrays</code>
<code> </code><code>if</code> <code>(right - left > counting_sort_threshold_for_short_or_char) {</code>
<code> </code><code>int</code><code>[] count = </code><code>new</code> <code>int</code><code>[num_char_values];</code>
<code> </code><code>for</code> <code>(</code><code>int</code> <code>i = left - </code><code>1</code><code>; ++i <= right;</code>
<code> </code><code>count[a[i]]++</code>
<code> </code><code>);</code>
<code> </code><code>for</code> <code>(</code><code>int</code> <code>i = num_char_values, k = right + </code><code>1</code><code>; k > left; ) {</code>
<code> </code><code>while</code> <code>(count[--i] == </code><code>0</code><code>);</code>
<code> </code><code>char</code> <code>value = (</code><code>char</code><code>) i;</code>
<code> </code><code>int</code> <code>s = count[i];</code>
<code> </code><code>do</code> <code>{</code>
<code> </code><code>a[--k] = value;</code>
<code> </code><code>} </code><code>while</code> <code>(--s > </code><code>0</code><code>);</code>
<code> </code><code>}</code>
<code> </code><code>} </code><code>else</code> <code>{ </code><code>// use dual-pivot quicksort on small arrays</code>
<code> </code><code>dosort(a, left, right);</code>
<code>private</code> <code>static</code> <code>void</code> <code>dosort(</code><code>char</code><code>[] a, </code><code>int</code> <code>left, </code><code>int</code> <code>right) {</code>
<code> </code><code>// use quicksort on small arrays</code>
<code> </code><code>if</code> <code>(right - left < quicksort_threshold) {</code>
<code> </code><code>sort(a, left, right, </code><code>true</code><code>);</code>
<code> </code><code>return</code><code>;</code>
<code> </code><code>} </code>
集合架構中,collections工具類支援兩種排序方法:
collections.sort(list<t> list);
collections.sort(list<t> list, comparator<? super t> c)
如果待排序的清單中是數字或者字元,可以直接使用collections.sort(list);
當需要排序的集合或數組不是單純的數字型時,需要自己定義排序規則,實作一個comparator比較器。
下面了解一下comparable和comparator的應用。
comparable 是排序接口,一個類實作了comparable接口,就意味着該類支援排序。
comparable 的定義如下:
<code>public</code> <code>interface</code> <code>comparable<t> {</code>
<code> </code><code>public</code> <code>int</code> <code>compareto(t o);</code>
<code>}</code>
接口中通過x.compareto(y) 來比較x和y的大小。若傳回負數,意味着x比y小;傳回零,意味着x等于y;傳回正數,意味着x大于y。
當然這裡的大于等于小于的意義是要根據我們的排序規則來了解的。
comparator是比較器接口,如果需要控制某個類的次序,而該類本身沒有實作comparable接口,也就是不支援排序,那麼可以建立一個類需要實作comparator接口即可,在這個接口裡制定具體的排序規則,
comparator接口的定義如下:
<code>public</code> <code>interface</code> <code>comparator<t> {</code>
<code> </code><code>int</code> <code>compare(t o1, t o2);</code>
<code> </code><code>boolean</code> <code>equals(object obj);</code>
<code>} </code>
一個比較器類要實作comparator接口一定要實作compareto(t o1, t o2) 函數,如果沒有必要,可以不去重寫equals() 函數。
因為在object類中已經實作了equals(object obj)函數方法。
int compare(t o1, t o2) 和上面的x.compareto(y)類似,定義排序規則後傳回正數,零和負數分别代表大于,等于和小于。
hashmap作為kay-value結構,本身是無序的,排序比較靈活,一般會通過一個list進行儲存。
下面的代碼針對hashmap的key和value排序,提供幾種實作的思路:
(1)轉換為key數組,按照key排序
<code>object[] key_arr = hashmap.keyset().toarray(); </code>
<code>arrays.sort(key_arr); </code>
<code>for</code> <code>(object key : key_arr) { </code>
<code> </code><code>object value = hashmap.get(key); </code>
<code>} </code>
(2)對hashmap的value進行排序
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<code>/**</code>
<code> </code><code>* 針對hashmap的value進行排序</code>
<code> </code><code>* @author bingyue</code>
<code> </code><code>*/</code>
<code>public</code> <code>class</code> <code>hashmapsort {</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) {</code>
<code> </code><code>hashmap<string, integer> map = </code><code>new</code> <code>hashmap<string, integer>(){{</code>
<code> </code><code>put(</code><code>"tom"</code><code>, </code><code>18</code><code>);</code>
<code> </code><code>put(</code><code>"jack"</code><code>, </code><code>25</code><code>);</code>
<code> </code><code>put(</code><code>"susan"</code><code>, </code><code>20</code><code>);</code>
<code> </code><code>put(</code><code>"rose"</code><code>, </code><code>38</code><code>);</code>
<code> </code><code>}};</code>
<code> </code>
<code> </code><code>valuecomparator cmptor = </code><code>new</code> <code>valuecomparator(map); </code>
<code> </code><code>/**</code>
<code> </code><code>* 轉換為有序的treemap進行輸出</code>
<code> </code><code>*/</code>
<code> </code><code>treemap<string, integer> sorted_map = </code><code>new</code> <code>treemap<string, integer>(cmptor);</code>
<code> </code><code>sorted_map.putall(map);</code>
<code> </code><code>for</code><code>(string sortedkey : sorted_map.keyset()){</code>
<code> </code><code>system.out.println(sortedkey+map.get(sortedkey));</code>
<code> </code><code>* 轉換為有序的list進行排序</code>
<code> </code><code>list<string> keys = </code><code>new</code> <code>arraylist<string>(map.keyset());</code>
<code> </code><code>collections.sort(keys, cmptor);</code>
<code> </code><code>for</code><code>(string key : keys) {</code>
<code> </code><code>system.out.println(key+map.get(key));</code>
<code> </code><code>static</code> <code>class</code> <code>valuecomparator </code><code>implements</code> <code>comparator<string> {</code>
<code> </code><code>hashmap<string, integer> base_map;</code>
<code> </code><code>public</code> <code>valuecomparator(hashmap<string, integer> base_map) {</code>
<code> </code><code>this</code><code>.base_map = base_map;</code>
<code> </code><code>public</code> <code>int</code> <code>compare(string arg0, string arg1) {</code>
<code> </code><code>if</code> <code>(!base_map.containskey(arg0) || !base_map.containskey(arg1)) {</code>
<code> </code><code>return</code> <code>0</code><code>;</code>
<code> </code><code>//按照value從小到大排序</code>
<code> </code><code>if</code> <code>(base_map.get(arg0) < base_map.get(arg1)) {</code>
<code> </code><code>return</code> <code>-</code><code>1</code><code>;</code>
<code> </code><code>} </code><code>else</code> <code>if</code> <code>(base_map.get(arg0) == base_map.get(arg1)) {</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
<code> </code><code>return</code> <code>1</code><code>;</code>
輸出:
tom18
susan20
jack25
rose38
tom18
susan20
rose38
如果你的list包裝的是基本類型或者string,隻要collections.sort(list)即可,
但是如果list中儲存的是實體bean等,就需要自己定義排序規則。
java可以對arraylist中的對象按照該對象某屬性排序,下面的操作實作對person實體清單的排序:
(1)定義person實體類
<code>public</code> <code>class</code> <code>person{</code>
<code> </code><code>string name;</code>
<code> </code><code>int</code> <code>age;</code>
<code> </code><code>public</code> <code>person(string name,</code><code>int</code> <code>age){</code>
<code> </code><code>this</code><code>.name = name;</code>
<code> </code><code>this</code><code>.age = age; </code>
<code> </code><code>}</code>
<code> </code><code>public</code> <code>int</code> <code>getage() {</code>
<code> </code><code>return</code> <code>age;</code>
<code> </code><code>public</code> <code>void</code> <code>setage(</code><code>int</code> <code>age) {</code>
<code> </code><code>this</code><code>.age = age;</code>
<code> </code><code>public</code> <code>string getname() {</code>
<code> </code><code>return</code> <code>name;</code>
<code> </code><code>public</code> <code>void</code> <code>setname(string name) {</code>
(2)實作comparator接口,編寫排序規則
<code>public</code> <code>class</code> <code>mycomparator </code><code>implements</code> <code>comparator{<br></code><code>// 實作comparator接口,也就是定義排序規則</code>
<code> </code><code>public</code> <code>int</code> <code>compare(object o1,object o2) {</code>
<code> </code><code>person p1=(person)o1;</code>
<code> </code><code>person p2=(person)o2;</code>
<code> </code><code>if</code><code>(p1.age<p2.age)</code>
<code> </code><code>return</code> <code>1</code><code>;</code>
<code> </code><code>else</code>
<code> </code><code>return</code> <code>0</code><code>;</code>
<code> </code><code>}</code>
(3)測試排序
<code>public</code> <code>class</code> <code>listsort {</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args){</code>
<code> </code><code>arraylist list = </code><code>new</code> <code>arraylist();</code>
<code> </code><code>list.add(</code><code>new</code> <code>person(</code><code>"lcl"</code><code>,</code><code>28</code><code>));</code>
<code> </code><code>list.add(</code><code>new</code> <code>person(</code><code>"fx"</code><code>,</code><code>23</code><code>));</code>
<code> </code><code>list.add(</code><code>new</code> <code>person(</code><code>"wqx"</code><code>,</code><code>29</code><code>));</code>
<code> </code><code>comparator comp = </code><code>new</code> <code>mycomparator();</code>
<code> </code><code>collections.sort(list,comp);</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>i = </code><code>0</code><code>;i<list.size();i++){</code>
<code> </code><code>person p = (person)list.get(i);</code>
<code> </code><code>system.out.println(p.getname());</code>
<code> </code><code>}</code>
<code> </code>
<code> </code><code>}</code>
<code> </code>