由Java中的Set,List,Map引出的排序技巧
一。關於概念:
List介面對Collection進行了簡單的擴充,它的具體實現類常用的有ArrayList和LinkedList。你可以將任何東
西放到一個List容器中,並在需要時從中取出。ArrayList從其命名中可以看出它是一種類似陣列的形式進行儲存,因此它的隨機訪問速度極快,而
LinkedList的內部實現是連結串列,它適合於在連結串列中間需要頻繁進行插入和刪除操作。在具體應用時可以根據需要自由選擇。前面說的Iterator只
能對容器進行向前遍歷,而ListIterator則繼承了Iterator的思想,並提供了對List進行雙向遍歷的方法。
Set介面也是Collection的一種擴充套件,而與List不同的時,在Set中的物件元素不能重複,也就是說你不能把同樣的東西兩次
放入同一個Set容器中。它的常用具體實現有HashSet和TreeSet類。HashSet能快速定位一個元素,但是你放到HashSet中的物件需
要實現hashCode()方法,它使用了前面說過的雜湊碼的演算法。而TreeSet則將放入其中的元素按序存放,這就要求你放入其中的物件是可排序的,
這就用到了集合框架提供的另外兩個實用類Comparable和Comparator。一個類是可排序的,它就應該實現Comparable介面。有時多
個類具有相同的排序演算法,那就不需要在每分別重複定義相同的排序演算法,只要實現Comparator介面即可。集合框架中還有兩個很實用的公用
類:Collections和Arrays。Collections提供了對一個Collection容器進行諸如排序、複製、查詢和填充等一些非常有用
的方法,Arrays則是對一個陣列進行類似的操作。
Map是一種把鍵物件和值物件進行關聯的容器,而一個值物件又可以是一個Map,依次類推,這樣就可形成一個多級對映。對於鍵物件來說,
像Set一樣,一個Map容器中的鍵物件不允許重複,這是為了保持查詢結果的一致性;如果有兩個鍵物件一樣,那你想得到那個鍵物件所對應的值物件時就有問
題了,可能你得到的並不是你想的那個值物件,結果會造成混亂,所以鍵的唯一性很重要,也是符合集合的性質的。當然在使用過程中,某個鍵所對應的值物件可能
會發生變化,這時會按照最後一次修改的值物件與鍵對應。對於值物件則沒有唯一性的要求。你可以將任意多個鍵都對映到一個值物件上,這不會發生任何問題(不
過對你的使用卻可能會造成不便,你不知道你得到的到底是那一個鍵所對應的值物件)。Map有兩種比較常用的實現:HashMap和TreeMap。
HashMap也用到了雜湊碼的演算法,以便快速查詢一個鍵,TreeMap則是對鍵按序存放,因此它便有一些擴充套件的方法,比如
firstKey(),lastKey()等,你還可以從TreeMap中指定一個範圍以取得其子Map。鍵和值的關聯很簡單,用pub(Object
key,Object value)方法即可將一個鍵與一個值物件相關聯。用get(Object key)可得到與此key物件所對應的值物件。
二.Java技巧:列表排序
在Java
Collection Framework中定義的List實現有Vector,ArrayList和LinkedList。這些集合提供了對物件組的索引訪問。他們提供了元素的新增與刪除支援。然而,它們並沒有內建的元素排序支援。
你能夠使用java.util.Collections類中的sort()方法對List元素進行排序。你既可以給方法傳遞一個List物件,也可以
傳遞一個List和一個Comparator。如果列表中的元素全都是相同型別的類,並且這個類實現了Comparable介面,你可以簡單的呼叫
Collections.sort()。如果這個類沒有實現Comparator,你也可以傳遞一個Comparator到方法sort()中,進行排
序。如果你不想使用預設的分類順序進行排序,你同樣可以傳遞一個Comparator到方法sort()中來進行排序。如果列表中的元素並不都是相同型別
的類,你在進行排序的時候就不是這樣幸運了。除非你編寫一個專用的跨類的Comparator。
排序的順序怎麼樣呢?如果元素是String物件,卻省的排序順序是按照字元編碼進行的,基本上是每個字元的ASCII/Unicode
值。如果嚴格的限制在處理英文,卻省的排序順序通常是足夠的,因為它首先排A-Z,然後是小寫字母a-z。然而如果你處理非英文字,或者你只是想使用不同
的排序順序,這樣Collections.sort()就出現了第二種變化。例如,你想使用字串的反序進行排序。為了實現這個功能,你可以在
Collections類中通過reverseOrder()來獲取一個反序Comparator。然後,你將反序Comparator傳遞給
sort()方法。換句話說,你作如下工作:
List list = ...; Comparator comp = Collections.reverseOrder(); Collections.sort(list, comp); |
如果列表包含專案:Man, man, Woman, 和woman,排序好的列表將是Man, Woman, man,
woman。這裡沒有什麼複雜的。需要注意的非常重要的一點是Collections.sort()是進行原位排序。如果你需要保留原序,需要先對原集合
進行復制,在排序,就像這樣:
List list = ...; List copyOfList = new ArrayList(list); Collections.sort(copyOfList); |
這裡,排好序的列表是:Man, Woman, man, woman,但是原始列表(Man, man, Woman, woman)被保留了。
到目前為止,排序是區分大小寫的。你如何進行不去分大小寫的排序呢?一種實現方式是象這樣實現Comparator:
public static class CaseInsensitiveComparator implements Comparator { public int compare(Object element1, Object element2) { String lower1 = element1.toString().toLowerCase(); String lower2 = element2.toString().toLowerCase(); return lower1.compareTo(lower2); } } |
你確實不需要手工的建立這個類。而是,你可以是用以存在的Comparator,CASE_INSENSIVTIVE_ORDER,它是在String類中定義的。
這種實現方式有一點小小的問題。Sort()演算法提供穩定的排序,並保持與原有序列相同的元素。這意味著一個包含兩個元素”woman”和”Woman”的列表將有不同的排序,而這種不同是根據兩個元素在列表中出現的先後次序決定的。
語言的不同又會怎麼樣呢?java.text包提供了Collector和CollectionKey類來進行區分語言的排序。這裡是例子:
注意,如果你的文字是本地語言,而不是預設語言,你需要傳遞一個本地語種給getInstance()方法,就象:
public static class CollatorComparator implements Comparator { Collator collator = Collator.getInstance(); public int compare(Object element1, Object element2) { CollationKey key1 = collator.getCollationKey( element1.toString()); CollationKey key2 = collator.getCollationKey( element2.toString()); return key1.compareTo(key2); } } |
你是在對集合關鍵字進行排序,而不是實際的字串。這不僅提供固定的不區分大小寫的排序,而且它是跨語種的排序。換句話說,如果你對西班牙文和非西班
牙文的混合詞進行排序,詞ma?ana
(tomorrow)將排在mantra的前面。如果你不使用Collector,ma?ana將排在mantra的後面。
下面這個程式
對一個列表進行不同型別的排序(預設的、區分大小寫的、區分語種的):
import java.awt.BorderLayout; import java.awt.Container; import java.io.*; import java.text.*; import java.util.*; import javax.swing.*; public class SortIt { public static class CollatorComparator implements Comparator { Collator collator = Collator.getInstance(); public int compare(Object element1, Object element2) { CollationKey key1 = collator.getCollationKey( element1.toString()); CollationKey key2 = collator.getCollationKey( element2.toString()); return key1.compareTo(key2); } } public static class CaseInsensitiveComparator implements Comparator { public int compare(Object element1, Object element2) { String lower1 = element1.toString(). toLowerCase(); String lower2 = element2.toString(). toLowerCase(); return lower1.compareTo(lower2); } } public static void main(String args[]) { String words[] = {"man", "Man", "Woman", "woman", "Manana", "manana", "ma?ana", "Ma?ana", "Mantra", "mantra", "mantel", "Mantel" }; // Create frame to display sortings JFrame frame = new JFrame("Sorting"); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); Container contentPane = frame.getContentPane(); JTextArea textArea = new JTextArea(); JScrollPane pane = new JScrollPane(textArea); contentPane.add(pane, BorderLayout.CENTER); // Create buffer for output StringWriter buffer = new StringWriter(); PrintWriter out = new PrintWriter(buffer); // Create initial list to sort List list = new ArrayList(Arrays.asList(words)); out.println("Original list:"); out.println(list); out.println(); // Perform default sort Collections.sort(list); out.println("Default sorting:"); out.println(list); out.println(); // Reset list list = new ArrayList(Arrays.asList(words)); // Perform case insensitive sort Comparator comp = new CaseInsensitiveComparator(); Collections.sort(list, comp); out.println("Case insensitive sorting:"); out.println(list); out.println(); // Reset list list = new ArrayList(Arrays.asList(words)); // Perform collation sort comp = new CollatorComparator(); Collections.sort(list, comp); out.println("Collator sorting:"); out.println(list); out.println(); // Fill text area and display textArea.setText(buffer.toString()); frame.pack(); frame.show(); } } |
如果你的主要問題是順序訪問,可能列表不是你的好的資料結構選擇。只要你的集合沒有重複,你可以在樹(TreeSet)中儲存你的元素(提供或不提供Comparator)。這樣,元素將總是排序形式的。
三.Collections.sort() 對 List 排序
import java.util.Comparator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
class User {
String name;
String age;
public User(String name,String age){
this.name=name;
this.age=age;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class ComparatorUser implements Comparator{
public int compare(Object arg0, Object arg1) {
User user0=(User)arg0;
User user1=(User)arg1;
//首先比較年齡,如果年齡相同,則比較名字
int flag=user0.getAge().compareTo(user1.getAge());
if(flag==0){
return user0.getName().compareTo(user1.getName());
}else{
return flag;
}
}
}
public class SortTest {
public static void main(String[] args){
List userlist=new ArrayList();
userlist.add(new User("dd","4"));
userlist.add(new User("aa","1"));
userlist.add(new User("ee","5"));
userlist.add(new User("bb","2"));
userlist.add(new User("ff","5"));
userlist.add(new User("cc","3"));
userlist.add(new User("gg","6"));
ComparatorUser comparator=new ComparatorUser();
Collections.sort(userlist, comparator);
for (int i=0;i<userlist.size();i++){
User user_temp=(User)userlist.get(i);
System.out.println(user_temp.getAge()+","+user_temp.getName());
}
}
}
//首先比較年齡,如果年齡相同,則比較名字
結果:
1, aa
2, bb
3, cc
4, dd
5, ee
5, ff
6, gg
四:Java.util.Collections.sort(List list)與Comparable,Comparator 介面
int thisVal = this.value;
int anotherVal = anotherInteger.value;
return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}
copyright © lizongbo
copyright © lizongbo
copyright © lizongbo
public int compare(Object a, Object b) {
int orderA = Integer.parseInt( ( (Image) a).getSequence());
int orderB = Integer.parseInt( ( (Image) b).getSequence());
return orderA - orderB;
}
});
copyright © lizongbo
具體可以參考學習例子有:
copyright © lizongbo
copyright © lizongbo
copyright © lizongbo
e.remove();
return (this == obj);
}
因此,放進在集合裡的元素,建議都重新實現自己的 equals方法
相關文章
- Java 中的泛型 集合(List,Set) MapJava泛型
- Java執行緒安全的集合類:Map、List、SetJava執行緒
- List、Set、Queue、Map
- List Set Map之間的不同
- 你對Collection中Set、List、Map理解?
- List,Set,Queue,Map介面
- Java集合體系總結 Set、List、Map、QueueJava
- Java8 中 List 轉 Map(Collectors.toMap) 使用技巧Java
- Java集合中List,Set以及Map等集合體系詳解(史上最全)Java
- set\list\map部分原始碼解析原始碼
- Scala——三個容器:List Set Map
- map和set對vector排序排序
- Java容器(List、Set、Map)知識點快速複習手冊Java
- java的各種集合為什麼不安全(List、Set、Map)以及代替方案Java
- 實戰小技巧19:List轉Map List的幾種姿勢
- Java : List中 根據map的某個key去重Java
- Java筆記——【List、Set】Java筆記
- JavaScript中的new map()和new set()使用詳細(new map()和new set()的區別)JavaScript
- list與Set、Map區別及適用場景
- ES6中的Map與Set集合
- map、unordered_map、set 和 unordered_set的小介紹
- 1、List 和 Set 、Map的區別-金三銀四跳槽季Java面試大綱(答案篇)Java面試
- Kotlin——高階篇(四):集合(Array、List、Set、Map)基礎Kotlin
- List集合按照由小到大排序或者由大到小排序排序
- 如何在Java 8中將List轉換為Map?Java
- Java中List集合轉Map集合報錯:Duplicate keyJava
- Java Map和List常見操作Java
- java中的Map集合Java
- 由專案需求中引出的思考,Promise鏈式呼叫如何防抖Promise
- Java基礎系列—List排序Java排序
- list中add、set方法詳解
- Python 的List 和tuple,Dict,SetPython
- Set 和Map
- 由哪個log先輸出引出的event loop思考OOP
- 沉浸進行時 —— 由Diegetic UI引出的概念學習UI
- python中的list,tuple,set和dict(參考python文件)Python
- list轉map,使用java8,stream流Java
- DevExpress中獲取GridControl排序之後的ListdevExpress排序
- 荷蘭國旗問題引出的三色排序排序