暫記(系統(tǒng)的認(rèn)識集合)
1. Java集合(container)
1.集合密末、數(shù)組都是對多個數(shù)據(jù)進(jìn)行存儲操作的結(jié)構(gòu),簡稱Java容器嚷掠。
說明:此時的存儲酸些,主要指的是內(nèi)存層面的存儲,不涉及到持久化的存儲(.txt,.jpg,.avi琐谤,數(shù)據(jù)庫中)
2.1 數(shù)組在存儲多個數(shù)據(jù)方面的特點:
一旦初始化以后蟆技,其長度就確定了。
數(shù)組一旦定義好斗忌,其元素的類型也就確定了质礼。我們也就只能操作指定類型的數(shù)據(jù)了。
比如:String[] arr;int[] arr1;Object[] arr2;
2.2 數(shù)組在存儲多個數(shù)據(jù)方面的缺點:
一旦初始化以后织阳,其長度就不可修改眶蕉。
數(shù)組中提供的方法非常有限,對于添加唧躲、刪除造挽、插入數(shù)據(jù)等操作,非常不便弄痹,同時效率不高饭入。
獲取數(shù)組中實際元素的個數(shù)的需求,數(shù)組沒有現(xiàn)成的屬性或方法可用
數(shù)組存儲數(shù)據(jù)的特點:有序肛真、可重復(fù)谐丢。對于無序、不可重復(fù)的需求泰鸡,不能滿足沉删。
二、集合框架
* |----Collection接口:單列集合哮奇,用來存儲一個一個的對象
* |----List接口:存儲有序的饭耳、可重復(fù)的數(shù)據(jù)串述。 -->“動態(tài)”數(shù)組
* |----ArrayList执解、LinkedList寞肖、Vector
*
* |----Set接口:存儲無序的、不可重復(fù)的數(shù)據(jù) -->高中講的“集合”
* |----HashSet衰腌、LinkedHashSet新蟆、TreeSet
*
* |----Map接口:雙列集合,用來存儲一對(key - value)一對的數(shù)據(jù) -->高中函數(shù):y = f(x)
* |----HashMap右蕊、LinkedHashMap琼稻、TreeMap、Hashtable饶囚、Properties
2. Collection接口方法
//向Collection接口的實現(xiàn)類的對象中添加數(shù)據(jù)obj時帕翻,要求obj所在類要重寫equals()
Collection coll = new ArrayList();
int size(); //大小
boolean isEmpty(); //是否為空
boolean contains(Object o); //是否包含 會去調(diào)用equals()
boolean containsAll(Collection<?> c);; //是否包含Collection對象中的數(shù)據(jù) 會去調(diào)用equals()
boolean add(E e); //添加一個元素
boolean addAll(Object o); //刪除coll1中的所有元素
boolean remove(Object o); //移除一個元素
boolean removeAll(Object o); //差集:從當(dāng)前集合中移除coll2中所有的元素
boolean retainAll(Object o); //交集:從當(dāng)前集合中和coll2中的交集,并返回給當(dāng)前集合
Collection coll1 = Arrays萝风。asList(123,456);
coll.addAll(coll1); //得到結(jié)果為:[123,456]
Collection coll2 = Arrays.asList(123,4567);
coll.removeAll(coll2); //得到結(jié)果為:[456]
coll1.retainAll(coll2); //得到結(jié)果:[123]
//集合轉(zhuǎn)數(shù)組 toArray()
Object[] arr = coll1.toArray();
//數(shù)組轉(zhuǎn)集合 Arrays類的靜態(tài)方法asList()
List<Object> objects = Arrays.asList(arr);
Iterator<E> iterator(); //用于遍歷集合
3. Iterator迭代器接口
- Iterator對象稱為迭代器(設(shè)計模式的一種)嘀掸,用于遍歷Collection集合中的元素。
//迭代器模式规惰,就是為容器而生
boolean hasNext(); //判斷是否還有下一個元素睬塌,有/true 否/false
E next(); //1.指針下移,2.將下一以后集合位置上的元素返回
default void remove(); //刪除集合元素(通過迭代器對象)
for(Iterator<String> iterator = c.iterator();iterator.hasNext();) {
String string = (String) iterator.next();
System.out.println(string);
}
// forEac 內(nèi)部也是調(diào)用了迭代器
for (Object obj : coll){
System.out.println(obj);
}
//ListIterator
ListIterator有hasPrevious()和previous()方法歇万,可以實現(xiàn)逆向(順序向前)遍歷
(記一下)......
4. Collection子接口 :List
* |----Collection接口:單列集合揩晴,用來存儲一個一個的對象
* |----List接口:存儲有序的、可重復(fù)的數(shù)據(jù)贪磺。 -->“動態(tài)”數(shù)組,替換原有的數(shù)組
* |----ArrayList:作為List接口的主要實現(xiàn)類硫兰;線程不安全的,效率高寒锚;底層使用Object[] elementData存儲
* |----LinkedList:對于頻繁的插入瞄崇、刪除操作,使用此類效率比ArrayList高壕曼;底層使用雙向鏈表存儲
* |----Vector:作為List接口的古老實現(xiàn)類苏研;線程安全的,效率低腮郊;底層使用Object[] elementData存儲
*
*
* 2. ArrayList的源碼分析:
* 2.1 jdk 7情況下
* ArrayList list = new ArrayList();//底層創(chuàng)建了長度是10的Object[]數(shù)組elementData
* list.add(123 );//elementData[0] = new Integer(123);
* ...
* list.add(11);//如果此次的添加導(dǎo)致底層elementData數(shù)組容量不夠摹蘑,則擴(kuò)容。
* 默認(rèn)情況下轧飞,擴(kuò)容為原來的容量的1.5倍衅鹿,同時需要將原有數(shù)組中的數(shù)據(jù)復(fù)制到新的數(shù)組中撒踪。
*
* 結(jié)論:建議開發(fā)中使用帶參的構(gòu)造器:ArrayList list = new ArrayList(int capacity)
*
* 2.2 jdk 8中ArrayList的變化:
* ArrayList list = new ArrayList();//底層Object[] elementData初始化為{}.并沒有創(chuàng)建長度為10的數(shù)組
*
* list.add(123);//第一次調(diào)用add()時,底層才創(chuàng)建了長度10的數(shù)組大渤,并將數(shù)據(jù)123添加到elementData[0]
* ...
* 后續(xù)的添加和擴(kuò)容操作與jdk 7 無異制妄。
* 2.3 小結(jié):jdk7中的ArrayList的對象的創(chuàng)建類似于單例的餓漢式,而jdk8中的ArrayList的對象
* 的創(chuàng)建類似于單例的懶漢式泵三,延遲了數(shù)組的創(chuàng)建耕捞,節(jié)省內(nèi)存。
*
* 3. LinkedList的源碼分析:
* LinkedList list = new LinkedList(); 內(nèi)部聲明了Node類型的first和last屬性烫幕,默認(rèn)值為null
* list.add(123);//將123封裝到Node中俺抽,創(chuàng)建了Node對象。
*
* 其中较曼,Node定義為:體現(xiàn)了LinkedList的雙向鏈表的說法
* private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
*
* 4. Vector的源碼分析:jdk7和jdk8中通過Vector()構(gòu)造器創(chuàng)建對象時磷斧,底層都創(chuàng)建了長度為10的數(shù)組。
* 在擴(kuò)容方面捷犹,默認(rèn)擴(kuò)容為原來的數(shù)組長度的2倍弛饭。
*
* 面試題:ArrayList、LinkedList萍歉、Vector三者的異同侣颂?
* 同:三個類都是實現(xiàn)了List接口,存儲數(shù)據(jù)的特點相同:存儲有序的翠桦、可重復(fù)的數(shù)據(jù)
* 不同:見上
//List接口中常用的方法
void add(int index, Object ele) ; //在index位置插入ele元素
boolean addAll(int index, Collection eles); //從index位置開始將eles中的所有元素添加進(jìn)來
Object get(int index); //獲取指定index位置的元素
int indexOf(Object obj); //返回obj在集合中首次出現(xiàn)的位置
int lastIndexOf(Object obj); //返回obj在當(dāng)前集合中末次出現(xiàn)的位置
Object remove(int index); //移除指定index位置的元素横蜒,并返回此元素
Object set(int index, Object ele); //設(shè)置指定index位置的元素為ele
List subList(int fromIndex, int toIndex); //返回從fromIndex到toIndex位置的子集合
總結(jié):常用方法
增:add(Object obj)
刪:remove(int index) / remove(Object obj)
改:set(int index, Object ele)
查:get(int index)
插:add(int index, Object ele)
長度:size()
遍歷:① Iterator迭代器方式
② 增強(qiáng)for循環(huán)
③ 普通的循環(huán)
5. Collection子接口 :Set
Set接口時Collection的子接口
* 1. Set接口的框架:
*
* |----Collection接口:單列集合,用來存儲一個一個的對象
* |----Set接口:存儲無序的销凑、不可重復(fù)的數(shù)據(jù) -->高中講的“集合”
* |----HashSet:作為Set接口的主要實現(xiàn)類丛晌;線程不安全的;可以存儲null值
* |----LinkedHashSet:作為HashSet的子類斗幼;遍歷其內(nèi)部數(shù)據(jù)時澎蛛,可以按照添加的順序遍歷
* 對于頻繁的遍歷操作,LinkedHashSet效率高于HashSet.
* |----TreeSet:可以按照添加對象的指定屬性蜕窿,進(jìn)行排序谋逻。
*
*
* 1. Set接口中沒有額外定義新的方法,使用的都是Collection中聲明過的方法桐经。
*
* 2. 要求:向Set(主要指:HashSet毁兆、LinkedHashSet)中添加的數(shù)據(jù),其所在的類一定要重寫hashCode()和equals()
* 要求:重寫的hashCode()和equals()盡可能保持一致性:相等的對象必須具有相等的散列碼
* 重寫兩個方法的小技巧:對象中用作 equals() 方法比較的 Field阴挣,都應(yīng)該用來計算hashCode 值气堕。
*
Set set = new HashSet();
基本方法繼承Collection
/*
一、Set:存儲無序的、不可重復(fù)的數(shù)據(jù)
以HashSet為例說明:
1. 無序性:不等于隨機(jī)性茎芭。存儲的數(shù)據(jù)在底層數(shù)組 中并非按照數(shù)組索引的順序添加揖膜,而是根據(jù)數(shù)據(jù)的哈希值決定的。
2. 不可重復(fù)性:保證添加的元素按照equals()判斷時梅桩,不能返回true.即:相同的元素只能添加一個壹粟。
二、添加元素的過程:以HashSet為例:
我們向HashSet中添加元素a,首先調(diào)用元素a所在類的hashCode()方法宿百,計算元素a的哈希值趁仙,
此哈希值接著通過某種算法計算出在HashSet底層數(shù)組中的存放位置(即為:索引位置),判斷
數(shù)組此位置上是否已經(jīng)有元素:
如果此位置上沒有其他元素犀呼,則元素a添加成功幸撕。 --->情況1
如果此位置上有其他元素b(或以鏈表形式存在的多個元素)薇组,則比較元素a與元素b的hash值:
如果hash值不相同外臂,則元素a添加成功。--->情況2
如果hash值相同律胀,進(jìn)而需要調(diào)用元素a所在類的equals()方法:
equals()返回true,元素a添加失敗
equals()返回false,則元素a添加成功宋光。--->情況2
對于添加成功的情況2和情況3而言:元素a 與已經(jīng)存在指定索引位置上數(shù)據(jù)以鏈表的方式存儲。
jdk 7 :元素a放到數(shù)組中炭菌,指向原來的元素罪佳。
jdk 8 :原來的元素在數(shù)組中,指向元素a
總結(jié):七上八下
HashSet底層:數(shù)組+鏈表的結(jié)構(gòu)黑低。
*/
Set set = new LinkHashSet();
基本方法繼承Collection
//LinkedHashSet的使用
//LinkedHashSet作為HashSet的子類赘艳,在添加數(shù)據(jù)的同時,每個數(shù)據(jù)還維護(hù)了兩個引用克握,記錄此數(shù)據(jù)前一個
//數(shù)據(jù)和后一個數(shù)據(jù)蕾管。
//優(yōu)點:對于頻繁的遍歷操作,LinkedHashSet效率高于HashSet
TreeSet
- TreeSet 是 SortedSet 接口的實現(xiàn)類菩暗,TreeSet 可以確保集合元素處于排序狀態(tài)掰曾。
- TreeSet底層使用紅黑樹結(jié)構(gòu)存儲數(shù)據(jù)
- TreeSet 兩種排序方法:自然排序和定制排序。默認(rèn)情況下停团,TreeSet 采用自然排序旷坦。
/*
1.向TreeSet中添加的數(shù)據(jù),要求是相同類的對象佑稠。
2.兩種排序方式:自然排序(實現(xiàn)Comparable接口) 和 定制排序(Comparator)
3.自然排序中秒梅,比較兩個對象是否相同的標(biāo)準(zhǔn)為:compareTo()返回0.不再是equals().
4.定制排序中,比較兩個對象是否相同的標(biāo)準(zhǔn)為:compare()返回0.不再是equals().
*/
6. Map接口
Map接口:雙列集合舌胶,用來存儲一對(key - value)一對的數(shù)據(jù) -->高中函數(shù):y = f(x)
/**
* 一捆蜀、Map的實現(xiàn)類的結(jié)構(gòu):
* |----Map:雙列數(shù)據(jù),存儲key-value對的數(shù)據(jù) ---類似于高中的函數(shù):y = f(x)
* |----HashMap:作為Map的主要實現(xiàn)類;線程不安全的漱办,效率高这刷;存儲null的key和value
* |----LinkedHashMap:保證在遍歷map元素時,可以按照添加的順序?qū)崿F(xiàn)遍歷娩井。
* 原因:在原有的HashMap底層結(jié)構(gòu)基礎(chǔ)上暇屋,添加了一對指針,指向前一個和后一個元素洞辣。
* 對于頻繁的遍歷操作咐刨,此類執(zhí)行效率高于HashMap。
* |----TreeMap:保證按照添加的key-value對進(jìn)行排序扬霜,實現(xiàn)排序遍歷定鸟。此時考慮key的自然排序或定制排序
* 底層使用紅黑樹
* |----Hashtable:作為古老的實現(xiàn)類;線程安全的著瓶,效率低联予;不能存儲null的key和value
* |----Properties:常用來處理配置文件。key和value都是String類型
*
*
* HashMap的底層:數(shù)組+鏈表 (jdk7及之前)
* 數(shù)組+鏈表+紅黑樹 (jdk 8)
*
*
* 面試題:
* 1. HashMap的底層實現(xiàn)原理材原?
* 2. HashMap 和 Hashtable的異同沸久?
* 3. CurrentHashMap 與 Hashtable的異同?(暫時不講)
* CurrentHashMap是用于多線程操作map中的數(shù)據(jù)所有的容器
* 分段鎖 把Map(共享數(shù)據(jù))分成多段余蟹,可以多個線程分別一起操作
*
* 二卷胯、Map結(jié)構(gòu)的理解:
* Map中的key:無序的、不可重復(fù)的威酒,使用Set存儲所有的key ---> key所在的類要重寫equals()和hashCode() (以HashMap為例)
* Map中的value:無序的窑睁、可重復(fù)的,使用Collection存儲所有的value --->value所在的類要重寫equals()
* 一個鍵值對:key-value構(gòu)成了一個Entry對象葵孤。
* Map中的entry:無序的担钮、不可重復(fù)的,使用Set存儲所有的entry
*
* 三佛呻、HashMap的底層實現(xiàn)原理裳朋?以jdk7為例說明:
* HashMap map = new HashMap():
* 在實例化以后,底層創(chuàng)建了長度是16的一維數(shù)組Entry[] table吓著。
* ...可能已經(jīng)執(zhí)行過多次put...
* map.put(key1,value1):
* 首先鲤嫡,調(diào)用key1所在類的hashCode()計算key1哈希值,此哈希值經(jīng)過某種算法計算以后绑莺,得到在Entry數(shù)組中的存放位置暖眼。
* 如果此位置上的數(shù)據(jù)為空,此時的key1-value1添加成功纺裁。 ----情況1
* 如果此位置上的數(shù)據(jù)不為空诫肠,(意味著此位置上存在一個或多個數(shù)據(jù)(以鏈表形式存在)),比較key1和已經(jīng)存在的一個或多個數(shù)據(jù)
* 的哈希值:
* 如果key1的哈希值與已經(jīng)存在的數(shù)據(jù)的哈希值都不相同司澎,此時key1-value1添加成功。----情況2
* 如果key1的哈希值和已經(jīng)存在的某一個數(shù)據(jù)(key2-value2)的哈希值相同栋豫,繼續(xù)比較:調(diào)用key1所在類的equals(key2)方法挤安,比較:
* 如果equals()返回false:此時key1-value1添加成功。----情況3
* 如果equals()返回true:使用value1替換value2丧鸯。
*
* 補(bǔ)充:關(guān)于情況2和情況3:此時key1-value1和原來的數(shù)據(jù)以鏈表的方式存儲蛤铜。
*
* 在不斷的添加過程中,會涉及到擴(kuò)容問題丛肢,當(dāng)超出臨界值(且要存放的位置非空)時围肥,擴(kuò)容。默認(rèn)的擴(kuò)容方式:擴(kuò)容為原來容量的2倍蜂怎,并將原有的數(shù)據(jù)復(fù)制過來穆刻。
*
* jdk8 相較于jdk7在底層實現(xiàn)方面的不同:
* 1. new HashMap():底層沒有創(chuàng)建一個長度為16的數(shù)組
* 2. jdk 8底層的數(shù)組是:Node[],而非Entry[]
* 3. 首次調(diào)用put()方法時,底層創(chuàng)建長度為16的數(shù)組
* 4. jdk7底層結(jié)構(gòu)只有:數(shù)組+鏈表杠步。jdk8中底層結(jié)構(gòu):數(shù)組+鏈表+紅黑樹氢伟。
* 4.1 形成鏈表時,七上八下(jdk7:新的元素指向舊的元素篮愉。jdk8:舊的元素指向新的元素)
4.2 當(dāng)數(shù)組的某一個索引位置上的元素以鏈表形式存在的數(shù)據(jù)個數(shù) > 8 且當(dāng)前數(shù)組的長度 > 64時腐芍,此時此索引位置上的所數(shù)據(jù)改為使用紅黑樹存儲差导。
*
* DEFAULT_INITIAL_CAPACITY : HashMap的默認(rèn)容量试躏,16
* DEFAULT_LOAD_FACTOR:HashMap的默認(rèn)加載因子:0.75
* threshold:擴(kuò)容的臨界值,=容量*填充因子:16 * 0.75 => 12
* TREEIFY_THRESHOLD:Bucket中鏈表長度大于該默認(rèn)值设褐,轉(zhuǎn)化為紅黑樹:8
* MIN_TREEIFY_CAPACITY:桶中的Node被樹化時最小的hash表容量:64
*
* 四颠蕴、LinkedHashMap的底層實現(xiàn)原理(了解)
* 源碼中:
* static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;//能夠記錄添加的元素的先后順序
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
*
*
* 五、Map中定義的方法:
添加助析、刪除犀被、修改操作:
Object put(Object key,Object value):將指定key-value添加到(或修改)當(dāng)前map對象中
void putAll(Map m):將m中的所有key-value對存放到當(dāng)前map中
Object remove(Object key):移除指定key的key-value對,并返回value
void clear():清空當(dāng)前map中的所有數(shù)據(jù)
元素查詢的操作:
Object get(Object key):獲取指定key對應(yīng)的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map中key-value對的個數(shù)
boolean isEmpty():判斷當(dāng)前map是否為空
boolean equals(Object obj):判斷當(dāng)前map和參數(shù)對象obj是否相等
元視圖操作的方法:
Set keySet():返回所有key構(gòu)成的Set集合
Collection values():返回所有value構(gòu)成的Collection集合
Set entrySet():返回所有key-value對構(gòu)成的Set集合
*總結(jié):常用方法:
* 添加:put(Object key,Object value)
* 刪除:remove(Object key)
* 修改:put(Object key,Object value)
* 查詢:get(Object key)
* 長度:size()
* 遍歷:keySet() / values() / entrySet()
*
*/
Properties
properties類是Hashtable的子類外冀,該對象用于處理屬性文件
由于屬性文件里的key寡键、value都是字符串類型,所有properties里的key和value都是字符串類型
存取數(shù)據(jù)時雪隧,建議使用setProperty(String key,String value)方法和getProperty(String key)方法
//這個地方不是很重要西轩,相應(yīng)的記一下,異常和關(guān)閉流就不貼出來了
Properties pros = new Properties();
FileInputStream fis = new FileInputStream("jdbc.properties");
pros.load(fis);//加載流對應(yīng)的文件
String name = pros.getProperty("name");
String password = pros.getProperty("password");
System.out.println("name = " + name + ", password = " + password);
7. Collections工具類
Collections:操作collection脑沿、Map的工具類
reverse(List):反轉(zhuǎn) List 中元素的順序
shuffle(List):對 List 集合元素進(jìn)行隨機(jī)排序
sort(List):根據(jù)元素的自然順序?qū)χ付?List 集合元素按升序排序
sort(List藕畔,Comparator):根據(jù)指定的 Comparator 產(chǎn)生的順序?qū)?List 集合元素進(jìn)行排序
swap(List,int庄拇, int):將指定 list 集合中的 i 處元素和 j 處元素進(jìn)行交換
Object max(Collection):根據(jù)元素的自然順序注服,返回給定集合中的最大元素
Object max(Collection韭邓,Comparator):根據(jù) Comparator 指定的順序,返回給定集合中的最大元素
Object min(Collection)
Object min(Collection溶弟,Comparator)
int frequency(Collection女淑,Object):返回指定集合中指定元素的出現(xiàn)次數(shù)
void copy(List dest,List src):將src中的內(nèi)容復(fù)制到dest中
boolean replaceAll(List list,Object oldVal辜御,Object newVal):使用新值替換 List 對象的所有舊值
List list = new ArrayList();
list.add(123);
list.add(43);
list.add(765);
list.add(-97);
list.add(0);
//報異常:IndexOutOfBoundsException("Source does not fit in dest")
// List dest = new ArrayList();
// Collections.copy(dest,list);
//正確的:
List dest = Arrays.asList(new Object[list.size()]);
System.out.println(dest.size());//list.size();
Collections.copy(dest,list);
System.out.println(dest);
/*
Collections 類中提供了多個 synchronizedXxx() 方法诗力,
該方法可使將指定集合包裝成線程同步的集合,從而可以解決
多線程并發(fā)訪問集合時的線程安全問題
*/
//返回的list1即為線程安全的List
List list1 = Collections.synchronizedList(list);
暫記我抠。
- 時間:2019-12-6 01:53:36