Java集合資料儲存的總結
一、集合框架
集合是容納資料的容器,java常用的集合體系圖如下。以集合中是否執行重複元素來分,主要有List和Set介面,List集合中可以有重複元素,Set集合集合中的元素不可重複,Iterator和List Iterator是遍歷集合的2個迭代器,Map是儲存Key/Value鍵值對的容器。
二、迭代器
迭代器的用法寫在後面,這裡說明Iterator和ListIterator的區別:
- Iterator在遍歷一個集合的過程中不能修改集合中的物件,ListIterator可以修改物件
- ListIterator從後往前遍歷,有hasPrevious()方法,Iterator沒有
- ListIterator可以在遍歷過程中進行新增元素操作,Iterator不能,否則會報
java.util.ConcurrentModificationException
異常。
三、List集合
List集合儲存不唯一、有序的物件,可以操作角標。
3.1 ArrayList
3.1.1內部實現
ArrayList也叫變長陣列,陣列的長度是固定的,ArrayList可以隨著元素的增多長度增加,內部實現為陣列。ArrayList在新增元素時首先會判斷長度,長度不夠時,長度擴充套件到原來到1.5倍,原陣列複製到新陣列。
3.1.2關鍵屬性
屬性 | 取值或結論 |
---|---|
是否允許重複 | 允許 |
是否有序 | 有序 |
是否允許為空 | 允許 |
是否執行緒安全 | 否 |
使用場景 | 多查詢、少增刪 |
3.1.3 測試示例
建立一個ArrayList物件,新增5個元素,其中一個為null:
arrayList.add("a1");
arrayList.add("a2");
arrayList.add(null);
arrayList.add("a3");
arrayList.add("a4");
System.out.println(arrayList);
- 1
- 2
- 3
- 4
- 5
- 6
列印結果:
[a1, a2, null, a3, a4]
- 1
使用迭代器for迴圈方式遍歷:
for (Iterator iter=arrayList.iterator();iter.hasNext();){
System.out.println(iter.next());
}
- 1
- 2
- 3
使用迭代器while迴圈方式遍歷:
Iterator iter=arrayList.iterator();
while (iter.hasNext()){
System.out.println(iter.next());
}
- 1
- 2
- 3
- 4
儲存自定義物件:
public class Boy {
private String name;
private int age;
//省略setter、getter、構造器和toString()方法
}
- 1
- 2
- 3
- 4
- 5
- 6
新增Boy物件到ArrayList中並列印:
ArrayList<Boy> boys=new ArrayList<>();
Boy b1=new Boy("Tom",12);
Boy b2=new Boy("Jack",11);
Boy b3=new Boy("Mike",15);
boys.add(b1);
boys.add(b2);
boys.add(b3);
System.out.println(boys);
Iterator<Boy> iter=boys.iterator();
while (iter.hasNext()){
Boy b=iter.next();
System.out.println(b.getName()+"----"+b.getAge());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
結果:
[Boy{name='Tom', age=12}, Boy{name='Jack', age=11}, Boy{name='Mike', age=15}]
Tom----12
Jack----11
Mike----15
- 1
- 2
- 3
- 4
- 5
3.1.4 轉成執行緒安全
非執行緒安全的ArrayList
ArrayList<String> arrayList = new ArrayList();
- 1
- 2
執行緒安全的ArrayList
List arrayList =Collections.synchronizedList(new ArrayList<String>()) ;
- 1
3.1.5 常用方法
- clear():移除列表中的所有元素
- contains(Object o): 包含指定元素
- get(int index):返回列表中指定位置上的元素
- indexOf(Object o): 返回列表中首次出現指定元素的索引,如果列表不包含,則返回-1
- isEmpty():列表為空返回true
- lastIndexOf(Object o):返回列表中最後一次出現指定元素的索引,如果列表不包含元素則返回-1
- remove(int index):移除列表中指定位置的元素
- remove(Object o):移除列表中首次出現的指定元素
- removeRange(int fromIndex,int toIndex):移除列表中索引在fromIndex(包括)和toIndex(不包括)之間的所有元素。
- size():返回集合的元素個數
- set(int index,E element):修改指定位置上的元素
- toArray():按順序返回包含此列表中所有元素的陣列
3.2 LinkedList
3.2.1內部實現
內部實現為雙向連結串列,刪除和增加速度快,查詢速度慢。
3.2.2關鍵屬性
屬性 | 取值或結論 |
---|---|
是否允許重複 | 允許 |
是否有序 | 有序 |
是否允許為空 | 允許 |
是否執行緒安全 | 否 |
使用場景 | 多增刪、少查詢 |
3.2.3 測試示例
LinkedList當作FIFO的佇列使用,也就是常用的add方法新增元素:
LinkedList quene=new LinkedList();
quene.add("a");
quene.add("b");
quene.add("c");
quene.add("d");
System.out.println("列印佇列:"+quene);
System.out.println("獲取隊頭:"+quene.getFirst());
System.out.println("獲取隊尾:"+quene.getLast());
System.out.println("移除隊頭:"+quene.pop());
System.out.println("移除隊頭之後的佇列:"+quene);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
列印結果:
列印佇列:[a, b, c, d]
獲取隊頭:a
獲取隊尾:d
移除隊頭:a
移除隊頭之後的佇列:[b, c, d]
- 1
- 2
- 3
- 4
- 5
LinkedList當作FILO的棧使用:
LinkedList stack = new LinkedList();
stack.push("1");
stack.push("2");
stack.push("3");
stack.push("4");
System.out.println("列印棧:"+stack);
System.out.println("獲取棧頂元素:"+stack.peek());
System.out.println("列印棧:"+stack);
System.out.println("取出棧頂元素:"+stack.pop());
System.out.println("列印棧:"+stack);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
列印結果:
列印棧:[4, 3, 2, 1]
獲取棧頂元素:4
列印棧:[4, 3, 2, 1]
取出棧頂元素:4
列印棧:[3, 2, 1]
- 1
- 2
- 3
- 4
- 5
除了ArrayList中包含的基本方法以為,LinkedList中多了getFirst()、getLast()、addFirst()、addLast()、peek()、peekFirst()、peekLast()、removeFirst()、removeLast()等方法。
3.2.4 轉成執行緒安全
List<Integer> linkedList=Collections.synchronizedList(new LinkedList<Integer>());
- 1
3.3 Vector
Vector內部是陣列結構,執行緒安全,速度較慢,幾乎不用。
四、Set集合
Set集合中的元素唯一、無序,沒有角標。
4.1HashSet
4.1.1內部實現
內部結構是雜湊表,物件存入HashSet之前,要先確保物件重寫equals()和hashCode()方法,這樣才能比較物件的值是否相等,確保set中沒有儲存相同的物件。判斷兩個元素是否相同,首先通過hashCode()方法判斷的是2個元素的雜湊值是否相同,再根據equals()方法判斷值是否相同,只有2者都相同才是統一元素。
4.1.2 基本屬性
屬性 | 取值或結論 |
---|---|
是否允許重複 | 不允許 |
是否有序 | 無序 |
是否允許為空 | 允許(只有一個null) |
是否執行緒安全 | 否 |
使用場景 | 物件不重複和需要快速查詢的場景 |
4.1.3 測試示例
HashSet<String> hashSet=new HashSet();
hashSet.add("abc");
hashSet.add("張三");
hashSet.add("李四");
hashSet.add("tim");
hashSet.add(null);
hashSet.add(null);
System.out.println("HashSet 大小:"+hashSet.size());
Iterator iter=hashSet.iterator();
while (iter.hasNext()){
System.out.println(iter.next());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
列印結果:
HashSet 大小:5
null
李四
張三
abc
tim
- 1
- 2
- 3
- 4
- 5
- 6
新增自定義物件,仍然新增Boy類中的物件
Boy b1=new Boy("神樂",12);
Boy b2=new Boy("神樂",12);
HashSet<Boy> boys=new HashSet<>();
boys.add(b1);
boys.add(b2);
System.out.println(boys);
- 1
- 2
- 3
- 4
- 5
- 6
結果:
[Boy{name='神樂', age=12}, Boy{name='神樂', age=12}]
- 1
這時候b1和b2其實是一個物件,在Boy類中重寫hashCode()和equals()方法:
public class Boy {
private String name;
private int age;
//省略setter、getter、構造器和toString()方法
@Override
public int hashCode() {
return name.hashCode()+age;
}
@Override
public boolean equals(Object obj) {
if (this==obj) return true;
if (!(obj instanceof Boy)) throw new ClassCastException("型別錯誤");
Boy boy=(Boy) obj;
return this.name.equals(boy.name)&&(this.age==boy.age);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
重寫equals和hashCode方法以後,上述集合中就會只新增一個物件:
[Boy{name='神樂', age=12}]
- 1
4.1.4 轉成執行緒安全
Set<String> hSet=Collections.synchronizedSet(new HashSet<String>());
- 1
4.1.5 唯一且有序
LinkedHashSet集合中都元素唯一且有序,這裡都有序是指新增順序。
LinkedHashSet<String> lHashSet= new LinkedHashSet<String>();
lHashSet.add("abc");
lHashSet.add("張三");
lHashSet.add("李四");
lHashSet.add("tim");
lHashSet.add(null);
iter=lHashSet.iterator();
while (iter.hasNext()){
System.out.println(iter.next());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
列印結果:
abc
張三
李四
tim
null
- 1
- 2
- 3
- 4
- 5
4.2 TreeSet
4.2.1 內部實現
TreeSet內部實現為二叉樹,可以對元素進行排序
4.2.2 基本屬性
屬性 | 取值或結論 |
---|---|
是否允許重複 | 不允許 |
是否有序 | 無序 |
是否允許為空 | 允許(只有一個null) |
是否執行緒安全 | 否 |
使用場景 | 去重且排序 |
4.2.3 測試示例
Boy b1=new Boy("定春",16);
Boy b2=new Boy("神樂",12);
Boy b3=new Boy("桑巴",13);
TreeSet<Boy> treeSet=new TreeSet<>(new Comparator<Boy>() {
@Override
public int compare(Boy o1, Boy o2) {
return o1.getAge()-o2.getAge();
}
});
treeSet.add(b1);
treeSet.add(b2);
treeSet.add(b3);
System.out.println(treeSet);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
列印結果:
[Boy{name='神樂', age=12}, Boy{name='桑巴', age=13}, Boy{name='定春', age=16}]
- 1
4.2.4 轉成執行緒安全
TreeSet<Boy> treeSet=new TreeSet<>(new Comparator<Boy>() {
@Override
public int compare(Boy o1, Boy o2) {
return o1.getAge()-o2.getAge();
}
});
Set<Boy> treeSet1=Collections.synchronizedSet(treeSet);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
五、Map集合
Map只儲存的是鍵值對,Key必須唯一且不為空,key允許為null。
5.1HashMap
5.1.1基本屬性
屬性 | 取值或結論 |
---|---|
是否允許重複 | key重複會被覆蓋,value可重複 |
是否有序 | 無序 |
是否允許為空 | key和value都允許為空 |
是否執行緒安全 | 否 |
5.1.2 測試示例
詞頻統計:
String[] arr={"Hadoop","Lucene","ES","ES","ES","Hadoop","Java","JS"};
//TreeMap<String,Integer> map=new TreeMap<>();
HashMap<String,Integer> map=new HashMap<>();
for (String str:arr){
if (map.containsKey(str)){
map.put(str,map.get(str)+1);
}else{
map.put(str,1);
}
}
Set<String> keys=map.keySet();
Iterator<String> iter=keys.iterator();
while (iter.hasNext()){
String str=iter.next();
System.out.println(str+"---"+map.get(str));
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
列印結果:
Java---1
Hadoop---2
JS---1
Lucene---1
ES---3
- 1
- 2
- 3
- 4
- 5
如果想按value排序,可以改成TreeMap();
六、效能對比
ArrayList遍歷效能對比
ArrayList的遍歷可以用一般for迴圈、foreach迴圈、Iterator迭代器三種方式實現,為了測試它們的效能,先建立一個ArrayList物件,新增5萬個字串:
ArrayList<String > a = new ArrayList();
for (int i = 0; i < 60000; i++) {
a.add(""+i);
}
- 1
- 2
- 3
- 4
for 迴圈列印並記錄耗時:
long start = System.currentTimeMillis();
for (int i = 0; i < a.size(); i++) {
System.out.print(a.get(i));
}
long end = System.currentTimeMillis();
System.out.println("\n下標for迴圈:" + (end - start));
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
結果:
150
- 1
foreach迴圈列印並記錄耗時:
start = System.currentTimeMillis();
for (String i : a) {
System.out.print(i);
}
end = System.currentTimeMillis();
System.out.println("\nforeach:" + (end - start));
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
耗時:
95
- 1
Iterator迴圈列印:
start=System.currentTimeMillis();
Iterator iter=a.iterator();
while (iter.hasNext()){
System.out.print(iter.next());
}
end=System.currentTimeMillis();
System.out.println("\nIter:"+(end-start));
- 1
- 2
- 3
- 4
- 5
- 6
- 7
耗時:
60
- 1
結論:一般for 迴圈最慢、foreach次之、Iterator最快。
另外,Iterator遍歷還有另外一種變形方式,效率和while形式一樣。
for(Iterator it=a.iterator();it.hasNext();){
System.out.print(it.next());
}
- 1
- 2
- 3
七、參考文章
有些文章總結的很好,列出來供參考學習:
Java集合框架
相關推薦
Java集合資料儲存的總結
一、集合框架 集合是容納資料的容器,java常用的集合體系圖如下。以集合中是否執行重複元素來分,主要有List和Set介面,List集合中可以有重複元素,Set集合集合中的元素不可重複,Iterator和List Iterator是遍歷集合的2個迭代器,Map是儲存Key/
Java集合框架知識總結
log 增強for循環 stat sort 訪問 字符串 繼承 操作類 map對象 兩大體系:Collection,Map 一、Collection: List 接口 : List:裏面對象全部是有序的(通過三種方法來遍歷) ArrayList,LinkedLis
java-集合各個特點總結
alt inf 集合 技術 技術分享 png div http mage java-集合各個特點總結
Java的資料結構總結
Java 基本資料型別總結 在Java的程式碼重構中,我們不得不承認若是不瞭解jvm的記憶體原理或是資料型別,我們根本讀不懂那些亂七八糟的資料引數。 變數就是申請記憶體來儲存值。也就是說,當建立變數的時候,需要在記憶體中申請空間;記憶體管理系統根據變數的型別為變數分配儲存空間
Java集合類的總結
依照實現介面分類: 實現Map介面的有:EnumMap、IdentityHashMap、HashMap、LinkedHashMap、WeakHashMap、TreeMap 實現List介面的有:ArrayList、LinkedList 實現Set介面的有:HashSet、Linke
java集合之List總結
主要驗證一下List集合的常用操作: list中新增,獲取,刪除元素; 新增方法是:.add(e); 獲取方法是:.get(index); 刪除方法是:.remove(index); 按照索引刪除; .remove(Object o); 按照元素內容刪除;
Java集合框架:總結
Java集合框架這個系列做了一個整理,主要包括: Map系:HashMap, LinkedHashMap, TreeMap, WeakHashMap, EnumMap; List系:ArrayList, LinkedList, Vector, Stack; Set系:HashSet, L
Java 集合 ,資料結構概述
collection集合分類: collection集合的遍歷: 使用迭代器進行遍歷 使用size()和get()方法結合進行遍歷 使用列表迭代器進行遍歷 用toArray()方法將集合轉化成陣列遍歷 注意:用列表迭代器進行遍歷時hasPrevious是判斷
Java集合類的總結與比較
Collection├List│├LinkedList│├ArrayList│└Vector│└Stack└Set Map├Hashtable├HashMap└WeakHashMap Collection介面Collection是最基本的集合介面,一個Collection代
Java集合框架問題總結
1.Java集合框架是什麼?說出一些集合框架的優點? 每種程式語言中都有集合,最初的Java版本包含幾種集合類:Vector、Stack、HashTable和Array。隨著集合的廣泛使用,Java1.2提出了囊括所有集合介面、實現和演算法的集合框架。在保證執行緒安全的情況
Java常用資料結構總結
資料元素相互之間的關係稱為結構。有四類基本結構:集合、線性結構、樹形結構、圖狀結構;集合結構:除了同屬於一種類型外,別無其它關係線性結構:元素之間存在一對一關係常見型別有: 陣列,連結串列,佇列,棧,它
JAVA集合框架學習總結
做一個JAVA簡單的集合框架的知識總結,只是單純的知識點記錄和自己的表達,更深入或具體的只能自己去查API或原始碼了,以後如果有其他想法再回來補充修正,有錯誤之處請指教。 java集合框架主要分為實現了Collection介面的List和Set、對映介面Map。
[Java]集合框架知識點總結(逐步更新)
1.迭代器 迭代器是一個介面,是一種取出集合中元素的方式。每個集合的內部以內部類的方式實現了此介面,用於取出集合的元素。這些內部類都符合迭代器介面。集合通過一個iterator方法提供這個取出元素的方式。不同的集合因為底層資料結構不同,而實現取出元素的方式不同。但都符合此介
Java集合 他人的總結 和 我的學習
以下網址是他人的總結, 值得我們學習! 感謝這些人的技術總結! 為什麼引入泛型: java 深入學習 JVM原理: Java類載入器:
Java泛型( 表示集合中儲存的資料的型別)
1.儲存字串 //建立一個集合儲存abcd //<E>就代表儲存元素資料的型別 //後面的<> 要跟前面的泛型保持一致 //jdk1.7出來的 菱形泛型 //如果前面聲明瞭泛型,後面的泛型可以省略不寫
Java集合框架篇-59-TreeSet儲存基本資料型別和自定義類物件
這篇開始,我們來學習Set介面的另外一個實現子類TreeSet。TreeSet一般是需要排序才使用的一種集合儲存方式,由於繼承了Set介面,TreeSet也能實現元素的唯一。下面通過兩個練習
Java集合類總結
tree dex trac emp oat err 條件 最終 一個地方 集合類和接口之間的關系圖,能夠比較清楚的展示各個類和接口之間的關系(其中:點框為接口(...) 短橫線框為抽象類(---) 實線為類) 上圖可以看到:集合可以分成兩部分來學習。一個是以Colle
Java集合類操作優化經驗總結
設置 mar ise long 初始化 實際類型 線性表 core 不一定 在實際的項目開發中會有非常多的對象,怎樣高效、方便地管理對象,成為影響程序性能與可維護性的重要環節。Java 提供了集合框架來解決此類問題。線性表、鏈表、哈希表等是經常使用的數據結構,在
Java中的常用集合類型總結
tar tro arr style spa htable blog html hset 1.可重復列表(List) LinkedList和ArrayList的區別:http://www.importnew.com/6629.html ArrayList vs. Linked
Java集合的總結
存儲方式 hashtable 存在 href city tab 分離 很快 定義 參考博客: http://www.jianshu.com/p/63e76826e852 http://www.cnblogs.com/LittleHann/p/3690187.html