天天看點

Java集合架構實作自定義排序

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&lt;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 &gt; 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 &lt;= 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 &gt; 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 &gt; </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 &lt; 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&lt;t&gt; list);

collections.sort(list&lt;t&gt; list, comparator&lt;? super t&gt; c)

如果待排序的清單中是數字或者字元,可以直接使用collections.sort(list);

當需要排序的集合或數組不是單純的數字型時,需要自己定義排序規則,實作一個comparator比較器。

下面了解一下comparable和comparator的應用。

comparable 是排序接口,一個類實作了comparable接口,就意味着該類支援排序。 

comparable 的定義如下:

<code>public</code> <code>interface</code> <code>comparable&lt;t&gt; {</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&lt;t&gt; {</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&lt;string, integer&gt; map = </code><code>new</code> <code>hashmap&lt;string, integer&gt;(){{</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&lt;string, integer&gt; sorted_map = </code><code>new</code> <code>treemap&lt;string, integer&gt;(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&lt;string&gt; keys = </code><code>new</code> <code>arraylist&lt;string&gt;(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&lt;string&gt; {</code>

<code>        </code><code>hashmap&lt;string, integer&gt; base_map;</code>

<code>        </code><code>public</code> <code>valuecomparator(hashmap&lt;string, integer&gt; 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) &lt; 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{&lt;br&gt;</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&lt;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&lt;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>