java list取值_Java集合详解
一、集合的由來
通常,我們的程序需要根據(jù)程序運(yùn)行時才知道創(chuàng)建多少個對象。但若非程序運(yùn)行,程序開發(fā)階段,我們根本不知道到底需要多少個數(shù)量的對象,甚至不知道它的準(zhǔn)確類型。為了滿足這些常規(guī)的編程需要,我們要求能在任何時候,任何地點創(chuàng)建任意數(shù)量的對象,而這些對象用什么來容納呢?我們首先想到了數(shù)組,但是數(shù)組只能放統(tǒng)一類型的數(shù)據(jù),而且其長度是固定的,那怎么辦呢?集合便應(yīng)運(yùn)而生了!
為了對集合有個更加深入的了解,可以看我的這一篇文章:用 Java 數(shù)組來實現(xiàn) ArrayList 集合 http://www.cnblogs.com/ysocean/p/6812674.html
二、集合是什么?
Java集合類存放于 java.util 包中,是一個用來存放對象的容器。
注意:①、集合只能存放對象。比如你存一個 int 型數(shù)據(jù) 1放入集合中,其實它是自動轉(zhuǎn)換成 Integer 類后存入的,Java中每一種基本類型都有對應(yīng)的引用類型。
②、集合存放的是多個對象的引用,對象本身還是放在堆內(nèi)存中。
③、集合可以存放不同類型,不限數(shù)量的數(shù)據(jù)類型。
三、Java 集合框架圖
發(fā)現(xiàn)一個特點,上述所有的集合類,除了 map 系列的集合,即左邊集合都實現(xiàn)了 Iterator 接口,這是一個用于遍歷集合中元素的接口,主要hashNext(),next(),remove()三種方法。它的一個子接口 ListIterator 在它的基礎(chǔ)上又添加了三種方法,分別是 add(),previous(),hasPrevious()。也就是說如果實現(xiàn) Iterator 接口,那么在遍歷集合中元素的時候,只能往后遍歷,被遍歷后的元素不會再被遍歷到,通常無序集合實現(xiàn)的都是這個接口,比如HashSet;而那些元素有序的集合,實現(xiàn)的一般都是 LinkedIterator接口,實現(xiàn)這個接口的集合可以雙向遍歷,既可以通過next()訪問下一個元素,又可以通過previous()訪問前一個 元素,比如ArrayList。
還有一個特點就是抽象類的使用。如果要自己實現(xiàn)一個集合類,去實現(xiàn)那些抽象的接口會非常麻煩,工作量很大。這個時候就可以使用抽象類,這些抽象類中給我們提供了許多
現(xiàn)成的實現(xiàn),我們只需要根據(jù)自己的需求重寫一些方法或者添加一些方法就可以實現(xiàn)自己需要的集合類,工作量大大降低。
四、集合詳解
①、Iterator:迭代器,它是Java集合的頂層接口(不包括 map 系列的集合,Map接口 是 map 系列集合的頂層接口)
Object next():返回迭代器剛越過的元素的引用,返回值是 Object,需要強(qiáng)制轉(zhuǎn)換成自己需要的類型
boolean hasNext():判斷容器內(nèi)是否還有可供訪問的元素
void remove():刪除迭代器剛越過的元素
所以除了 map 系列的集合,我們都能通過迭代器來對集合中的元素進(jìn)行遍歷。
注意:我們可以在源碼中追溯到集合的頂層接口,比如 Collection 接口,可以看到它繼承的是類 Iterable
那這就得說明一下 Iterator 和 Iterable 的區(qū)別:
Iterable :存在于 java.lang 包中。
我們可以看到,里面封裝了 Iterator 接口。所以只要實現(xiàn)了只要實現(xiàn)了Iterable接口的類,就可以使用Iterator迭代器了。
Iterator :存在于 java.util 包中。核心的方法next(),hasnext(),remove()。
這里我們引用一個Iterator 的實現(xiàn)類 ArrayList 來看一下迭代器的使用:暫時先不管 List 集合是什么,只需要看看迭代器的用法就行了
1 //產(chǎn)生一個 List 集合,典型實現(xiàn)為 ArrayList。
2 List list = new ArrayList();
3 //添加三個元素
4 list.add("Tom");
5 list.add("Bob");
6 list.add("Marry");
7 //構(gòu)造 List 的迭代器
8 Iterator it = list.iterator();
9 //通過迭代器遍歷元素
10 while(it.hasNext()){
11 Object obj = it.next();
12 System.out.println(obj);
13 }
②、Collection:List 接口和 Set 接口的父接口
看一下 Collection 集合的使用例子:
1 //我們這里將 ArrayList集合作為 Collection 的實現(xiàn)類
2 Collection collection = new ArrayList();
3
4 //添加元素
5 collection.add("Tom");
6 collection.add("Bob");
7
8 //刪除指定元素
9 collection.remove("Tom");
10
11 //刪除所有元素
12 Collection c = new ArrayList();
13 c.add("Bob");
14 collection.removeAll(c);
15
16 //檢測是否存在某個元素
17 collection.contains("Tom");
18
19 //判斷是否為空
20 collection.isEmpty();
21
22 //利用增強(qiáng)for循環(huán)遍歷集合
23 for(Object obj : collection){
24 System.out.println(obj);
25 }
26 //利用迭代器 Iterator
27 Iterator iterator = collection.iterator();
28 while(iterator.hasNext()){
29 Object obj = iterator.next();
30 System.out.println(obj);
31 }
③、List :有序,可以重復(fù)的集合。
由于 List 接口是繼承于 Collection 接口,所以基本的方法如上所示。
1、List 接口的三個典型實現(xiàn):
①、List list1 = new ArrayList();
底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,查詢快,增刪慢;線程不安全,效率高
②、List list2 = new Vector();
底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,查詢快,增刪慢;線程安全,效率低,幾乎已經(jīng)淘汰了這個集合
③、List list3 = new LinkedList();
底層數(shù)據(jù)結(jié)構(gòu)是鏈表,查詢慢,增刪快;線程不安全,效率高
怎么記呢?我們可以想象:
數(shù)組就像身上編了號站成一排的人,要找第10個人很容易,根據(jù)人身上的編號很快就能找到。但插入、刪除慢,要望某個位置插入或刪除一個人時,后面的人身上的編號都要變。當(dāng)然,加入或刪除的人始終末尾的也快。
鏈表就像手牽著手站成一圈的人,要找第10個人不容易,必須從第一個人一個個數(shù)過去。但插入、刪除快。插入時只要解開兩個人的手,并重新牽上新加進(jìn)來的人的手就可以。刪除一樣的道理。
2、除此之外,List 接口遍歷還可以使用普通 for 循環(huán)進(jìn)行遍歷,指定位置添加元素,替換元素等等。
1 //產(chǎn)生一個 List 集合,典型實現(xiàn)為 ArrayList
2 List list = new ArrayList();
3 //添加三個元素
4 list.add("Tom");
5 list.add("Bob");
6 list.add("Marry");
7 //構(gòu)造 List 的迭代器
8 Iterator it = list.iterator();
9 //通過迭代器遍歷元素
10 while(it.hasNext()){
11 Object obj = it.next();
12 //System.out.println(obj);
13 }
14
15 //在指定地方添加元素
16 list.add(2, 0);
17
18 //在指定地方替換元素
19 list.set(2, 1);
20
21 //獲得指定對象的索引
22 int i=list.indexOf(1);
23 System.out.println("索引為:"+i);
24
25 //遍歷:普通for循環(huán)
26 for(int j=0;j
27 System.out.println(list.get(j));
28 }
④、Set:典型實現(xiàn) HashSet()是一個無序,不可重復(fù)的集合
1、Set hashSet = new HashSet();
①、HashSet:不能保證元素的順序;不可重復(fù);不是線程安全的;集合元素可以為 NULL;
②、其底層其實是一個數(shù)組,存在的意義是加快查詢速度。我們知道在一般的數(shù)組中,元素在數(shù)組中的索引位置是隨機(jī)的,元素的取值和元素的位置之間不存在確定的關(guān)系,因此,在數(shù)組中查找特定的值時,需要把查找值和一系列的元素進(jìn)行比較,此時的查詢效率依賴于查找過程中比較的次數(shù)。而 HashSet 集合底層數(shù)組的索引和值有一個確定的關(guān)系:index=hash(value),那么只需要調(diào)用這個公式,就能快速的找到元素或者索引。
③、對于 HashSet: 如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應(yīng)該相同。
1、當(dāng)向HashSet集合中存入一個元素時,HashSet會先調(diào)用該對象的hashCode()方法來得到該對象的hashCode值,然后根據(jù)hashCode值決定該對象在HashSet中的存儲位置
1.1、如果 hashCode 值不同,直接把該元素存儲到 hashCode() 指定的位置
1.2、如果 hashCode 值相同,那么會繼續(xù)判斷該元素和集合對象的 equals() 作比較
1.2.1、hashCode 相同,equals 為 true,則視為同一個對象,不保存在 hashSet()中
1.2.2、hashCode 相同,equals 為 false,則存儲在之前對象同槽位的鏈表上,這非常麻煩,我們應(yīng)該約束這種情況,即保證:如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應(yīng)該相同。
注意:每一個存儲到 哈希 表中的對象,都得提供 hashCode() 和 equals() 方法的實現(xiàn),用來判斷是否是同一個對象
對于 HashSet 集合,我們要保證如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應(yīng)該相同。
常見的 hashCode()算法:
2、Set linkedHashSet = new LinkedHashSet();
①、不可以重復(fù),有序
因為底層采用 鏈表 和 哈希表的算法。鏈表保證元素的添加順序,哈希表保證元素的唯一性
3、Set treeSet = new TreeSet();
TreeSet:有序;不可重復(fù),底層使用 紅黑樹算法,擅長于范圍查詢。
* 如果使用 TreeSet() 無參數(shù)的構(gòu)造器創(chuàng)建一個 TreeSet 對象, 則要求放入其中的元素的類必須實現(xiàn) Comparable 接口所以, 在其中不能放入 null 元素
* 必須放入同樣類的對象.(默認(rèn)會進(jìn)行排序) 否則可能會發(fā)生類型轉(zhuǎn)換異常.我們可以使用泛型來進(jìn)行限制
4Set treeSet = new TreeSet();
treeSet.add(1); //添加一個 Integer 類型的數(shù)據(jù)
treeSet.add("a"); //添加一個 String 類型的數(shù)據(jù)
System.out.println(treeSet); //會報類型轉(zhuǎn)換異常的錯誤
?
* 自動排序:添加自定義對象的時候,必須要實現(xiàn) Comparable 接口,并要覆蓋 compareTo(Object obj) 方法來自定義比較規(guī)則
如果 this > obj,返回正數(shù) 1
如果 this < obj,返回負(fù)數(shù) -1
如果 this = obj,返回 0 ,則認(rèn)為這兩個對象相等
* 兩個對象通過 Comparable 接口 compareTo(Object obj) 方法的返回值來比較大小, 并進(jìn)行升序排列
* 定制排序: 創(chuàng)建 TreeSet 對象時, 傳入 Comparator 接口的實現(xiàn)類. 要求: Comparator 接口的 compare 方法的返回值和 兩個元素的 equals() 方法具有一致的返回值
public class TreeSetTest {
public static void main(String[] args) {
Person p1 = new Person(1);
Person p2 = new Person(2);
Person p3 = new Person(3);
Set set = new TreeSet<>(new Person());
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set); //結(jié)果為[1, 2, 3]
}
}
class Person implements Comparator{
public int age;
public Person(){}
public Person(int age){
this.age = age;
}
@Override
/***
* 根據(jù)年齡大小進(jìn)行排序
*/
public int compare(Person o1, Person o2) {
// TODO Auto-generated method stub
if(o1.age > o2.age){
return 1;
}else if(o1.age < o2.age){
return -1;
}else{
return 0;
}
}
@Override
public String toString() {
// TODO Auto-generated method stub
return ""+this.age;
}
}
* 當(dāng)需要把一個對象放入 TreeSet 中,重寫該對象對應(yīng)的 equals() 方法時,應(yīng)保證該方法與 compareTo(Object obj) 方法有一致的結(jié)果
以上三個 Set 接口的實現(xiàn)類比較:
共同點:1、都不允許元素重復(fù)
2、都不是線程安全的類,解決辦法:Set set = Collections.synchronizedSet(set 對象)
不同點:
HashSet:不保證元素的添加順序,底層采用 哈希表算法,查詢效率高。判斷兩個元素是否相等,equals() 方法返回 true,hashCode() 值相等。即要求存入 HashSet 中的元素要覆蓋 equals() 方法和 hashCode()方法
LinkedHashSet:HashSet 的子類,底層采用了 哈希表算法以及 鏈表算法,既保證了元素的添加順序,也保證了查詢效率。但是整體性能要低于 HashSet
TreeSet:不保證元素的添加順序,但是會對集合中的元素進(jìn)行排序。底層采用 紅-黑 樹算法(樹結(jié)構(gòu)比較適合范圍查詢)
⑤、Map:key-value 的鍵值對,key 不允許重復(fù),value 可以
1、嚴(yán)格來說 Map 并不是一個集合,而是兩個集合之間 的映射關(guān)系。
2、這兩個集合沒每一條數(shù)據(jù)通過映射關(guān)系,我們可以看成是一條數(shù)據(jù)。即 Entry(key,value)。Map 可以看成是由多個 Entry 組成。
3、因為 Map 集合即沒有實現(xiàn)于 Collection 接口,也沒有實現(xiàn) Iterable 接口,所以不能對 Map 集合進(jìn)行 for-each 遍歷。
?
Map hashMap = new HashMap<>();
//添加元素到 Map 中
hashMap.put("key1", "value1");
hashMap.put("key2", "value2");
hashMap.put("key3", "value3");
hashMap.put("key4", "value4");
hashMap.put("key5", "value5");
//刪除 Map 中的元素,通過 key 的值
hashMap.remove("key1");
//通過 get(key) 得到 Map 中的value
Object str1 = hashMap.get("key1");
//可以通過 添加 方法來修改 Map 中的元素
hashMap.put("key2", "修改 key2 的 Value");
//通過 map.values() 方法得到 Map 中的 value 集合
Collection
?
value = hashMap.values();
Java交流裙:109--1181--875
相關(guān)學(xué)習(xí)資料
集合
http://www.makeru.com.cn/live/1394_258.html?s=156461
java-環(huán)境搭建及基礎(chǔ)語法
http://www.makeru.com.cn/live/1394_202.html?s=156461
Java基礎(chǔ)
http://www.makeru.com.cn/course/details/2065?s=156461
?
總結(jié)
以上是生活随笔為你收集整理的java list取值_Java集合详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql性能优化金字塔法则pdf_My
- 下一篇: python读取excel送到网页_py