Java—Collection、Map、树
Collection? <類(lèi)型>
? ? List?可以重復(fù),有順序? ?可存放多個(gè)null值
? ? ? ? ? ? ArrayList??? ?主選?
? ? ? ? ? ? 結(jié)構(gòu):數(shù)組? ? ? 特點(diǎn):查找快,增刪慢? ? ? ? ?線程不安全,效率高
? ? ? ? ? ? Vector
? ? ? ? ? ? 結(jié)構(gòu):數(shù)組? ? ? 特點(diǎn):查找快,增刪慢? ? ? ? ? synchronized實(shí)現(xiàn)線程安全,效率低
? ? ? ? ? ? Stack?
? ? ? ? ? ? 結(jié)構(gòu):棧? ? ? ? ? 特點(diǎn):Vector的子類(lèi),也定義了自己的一些方法。? ? ? ?synchronized實(shí)現(xiàn)線程安全,效率低
? ? ? ? ? ? LinkedList
? ? ? ? ? ? 結(jié)構(gòu):鏈表? ? ? 特點(diǎn):查找慢,增刪快? ? ? ? ? 線程不安全,效率低
boolean add(E o) 向列表的尾部追加指定的元素void add(int index,E element) 在列表的指定位置插入指定元素。boolean addAll(Collection<? extends E> c) 追加指定 collection中的所有元素到此列表的結(jié)尾,順序是指定collection的迭代器返回這些元素的順序。boolean addAll(int index,Collection<? extends E> c) 將指定collection中的所有元素都插入到列表中的指定位置。void clear() 從列表中移除所有元素。boolean contains(Object o) 如果列表包含指定的元素,則返回true。boolean containsAll(Collection<?> c) 如果列表包含指定collection的所有元素,則返回true。boolean equals(Object c) 比較指定的對(duì)象與列表是否相等。E get(int index) 返回列表中指定位置的元素。int hashCode() 返回列表的哈希碼值。int indexOf(Object o) 返回列表中首次出現(xiàn)指定元素的索引,如果列表不包含此元素,則返回-1。boolean isEmpty() 判斷集合是否為空 如果為空 則返回true,否則返回falseIterator<E> iterator() 返回以正確順序在列表的元素上進(jìn)行迭代的迭代器。int lastIndexOf(Object o) 返回列表中最后出現(xiàn)指定元素的索引,如果列表不包含此元素,則返回-1。ListIterator<E> listIterator() 返回列表中元素的列表迭代器(以正確的順序)。ListIterator<E> listIterator(int index)返回列表中元素的列表迭代器(以正確的順序),從列表的指定位置開(kāi)始。E remove(int index) 移除列表中指定位置的元素。boolean remove(Object o) 移除列表中出現(xiàn)的首個(gè)指定元素。boolean removeAll(Collection<?> c) 從列表中移除指定collection中包含的所有元素。boolean retainAll(Collection<?> c)僅在列表中保留指定collection中所包含的元素。E set(int index,E element) 用指定元素替換列表中指定位置的元素。int size() 返回列表中的元素?cái)?shù)。List<E> subList(int forIndex,int toIndex) 返回列表中指定的formIndex(包括) 和toIndex(不包括)之間的部分視圖。Object toArray() 返回以正確順序包含列表中的所有元素的數(shù)組。? ? Set? 唯一性,沒(méi)有順序? ?只可存放一個(gè)null值
? ? ? ? ? ? HashSet?
? ? ? ? ? ? 結(jié)構(gòu):哈希表? ? ?通過(guò)hashCode()、equals()保證元素的唯一性? ? ?元素的排列是無(wú)序的? ?線程不安全
? ? ? ? ? ? 基于 HashMap 實(shí)現(xiàn)的,HashSet 底層使用 HashMap 來(lái)保存所有元素
? ? ? ? ? ? LinkedHashSet
? ? ? ? ? ? 結(jié)構(gòu):鏈表+哈希表? ?與HashSet相比,由鏈表保證元素有序? ?線程不安全
? ? ? ? ? ? TreeSet
? ? ? ? ? ? 結(jié)構(gòu):紅黑樹(shù)? ? ?排序方法有自然排序、比較器排序? ? 唯一性通過(guò)存放值時(shí)比較返回值是否為0,0既有相同值? ?線程不安全
? ? ? ? ? ? TreeSet實(shí)現(xiàn)了對(duì)TreeMap的封裝
? ? ? ? ? ? 實(shí)現(xiàn)了Serializable接口,因此它支持序列化,實(shí)現(xiàn)了Cloneable接口,能被克隆
Hash值沖突
? ? hash值沖突是發(fā)生在put()時(shí),hash值是通過(guò)hash(key.hashCode())來(lái)獲取的,因?yàn)閔ashCode是int類(lèi)型,所以最多只能說(shuō)2^32個(gè),當(dāng)put的元素越來(lái)越多時(shí),出現(xiàn)不同的key產(chǎn)生相同的hash值問(wèn)題,也即是hash沖突。
分離鏈表法
? ? 對(duì)于相同的哈希值,使用鏈表進(jìn)行連接。使用數(shù)組存儲(chǔ)每一個(gè)鏈表。
? ? put的時(shí)候地址上存在value,則再對(duì)比key是否相同,若hash值和key都相同,則替換value,若hash值相同,key不相同,則形成一個(gè)單鏈表,將hash值相同,key不同的元素以Entry<V,V>的方式存放在鏈表中,這樣就解決了hash沖突。
開(kāi)放地址方法
? ? ? ? ? ? 按順序決定哈希值時(shí),如果某數(shù)據(jù)的哈希值已經(jīng)存在,則在原來(lái)哈希值的基礎(chǔ)上往后加一個(gè)單位,直至不發(fā)生哈希沖突。
equals 和 hashCode區(qū)別:
- 在Object類(lèi)中,hashCode是一個(gè)本地方法簡(jiǎn)單理解為獲取對(duì)象地址,equals方法比較自己和obj對(duì)象地址是否相 等。在這里一定先認(rèn)識(shí)到這兩個(gè)方法,一個(gè)是取地址,一個(gè)是比較地址。equals()和hashCode()都不是final方法。
- hashCode()是一個(gè)native方法,而且返回值類(lèi)型是整形;該native方法將對(duì)象在內(nèi)存中的地址作為哈希碼返回,可以保證不超出整形范圍的情況下不同對(duì)象的返回值不同。
- 當(dāng)我們向哈希表(如HashSet、HashMap等)中添加對(duì)象object時(shí),首先調(diào)用hashCode()方法計(jì)算object的哈希碼,通過(guò)哈希碼可以直接定位object在哈希表中的位置(一般是哈希碼對(duì)哈希表大小取余)。如果該位置沒(méi)有對(duì)象,可以直接將object插入該位置;如果該位置有對(duì)象(可能有多個(gè),通過(guò)鏈表實(shí)現(xiàn)),則調(diào)用equals()方法比較這些對(duì)象與object是否相等,如果相等,則不需要保存object;如果不相等,則將該對(duì)象加入到鏈表中。
注:當(dāng)我們把自定義類(lèi)作為Map的Key的時(shí)候,需要重寫(xiě)HashCode跟equals方法,原因是要遵循equals相等,hashCode也一定相等,hashCode相等,equals不一定相等的規(guī)則。String就重寫(xiě)的這兩個(gè)方法。
Map<key,value>
? ? HashMap? ? 主選
? ? ? ? ? ? 結(jié)構(gòu):哈希表(數(shù)組+鏈表)? 無(wú)序的 只允許一個(gè)key為null,可多個(gè)值為null? ??線程不安全
? ? ? ? ? ? 采用分離鏈表法解決沖突
? ? ? ? ? ? 通過(guò)hashCode()、equals()保證元素的唯一性,hashCode()確定數(shù)組位置,equlas()確定是否可存放在鏈表。
? ? ? ? ? ? 實(shí)現(xiàn)了Serializable接口,因此它支持序列化,實(shí)現(xiàn)了Cloneable接口,能被克隆。
? ? ? ? ? ??JDK1.8增加了紅黑樹(shù)來(lái)進(jìn)行優(yōu)化。即當(dāng)鏈表超過(guò)8時(shí),鏈表就轉(zhuǎn)換為紅黑樹(shù),利用紅黑樹(shù)快速增刪改查的特點(diǎn)提高HashMap的性能。
? ? ? ? ? ? 缺點(diǎn):多線程put會(huì)陷入死循環(huán),因?yàn)镋ntry鏈表形成環(huán)形數(shù)據(jù)結(jié)構(gòu),查找時(shí)會(huì)陷入死循環(huán)。用迭代器遍歷時(shí)修改集合結(jié)構(gòu)會(huì)發(fā)生錯(cuò)誤。
? ? ? ? ? ? 遍歷方法:
Map<Integer, Integer> map = new HashMap<Integer, Integer>();Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();while (entries.hasNext()) {Map.Entry<Integer, Integer> entry = entries.next();System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());}? ?LinkedHashMap??
? ? ? ? ? ? 結(jié)構(gòu):數(shù)組+雙鏈表
? ? ? ? ? ? 與HashMap相比,LinkedHashMap 的元素是有序的,在LruCache中有使用,因?yàn)槭荓RU,最近最少使用算法需要支持有序。
? ?HashTable
? ? ? ? ? ? 結(jié)構(gòu):哈希表? ? ?key還是value都不能為null? ?synchronized實(shí)現(xiàn)線程安全
? ? ? ? ? ? 實(shí)現(xiàn)了Serializable接口,它支持序列化,實(shí)現(xiàn)了Cloneable接口,能被克隆
? ?TreeMap
? ? ? ? ? ? 結(jié)構(gòu):紅黑樹(shù)? ? ??排序方法有自然排序、比較器排序? ? ? 線程不安全? 可以插入null鍵,null值;
? ? ? ? ? ??無(wú)序集合(插入和遍歷順序不一致)
常用方法:
void clear() 從此映射中移除所有映射關(guān)系(可選操作)。boolean containsKey(Object key) 如果此映射包含指定鍵的映射關(guān)系,則返回 true。boolean containsValue(Object value) 如果此映射將一個(gè)或多個(gè)鍵映射到指定值,則返回 true。Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射關(guān)系的 Set 視圖。boolean equals(Object o) 比較指定的對(duì)象與此映射是否相等。V get(Object key) 返回指定鍵所映射的值;如果此映射不包含該鍵的映射關(guān)系,則返回 null。int hashCode() 返回此映射的哈希碼值。boolean isEmpty() 如果此映射未包含鍵-值映射關(guān)系,則返回 true。Set<K> keySet() 返回此映射中包含的鍵的 Set 視圖。V put(K key, V value) 將指定的值與此映射中的指定鍵關(guān)聯(lián)(可選操作)。void putAll(Map<? extends K,? extends V> m) 從指定映射中將所有映射關(guān)系復(fù)制到此映射中(可選操作)。V remove(Object key) 如果存在一個(gè)鍵的映射關(guān)系,則將其從此映射中移除(可選操作)。int size() 返回此映射中的鍵-值映射關(guān)系數(shù)。Collection<V> values() 返回此映射中包含的值的 Collection 視圖。Queue? FIFO隊(duì)列
操作失敗就拋出異常add(E e):添加一個(gè)元素到隊(duì)尾remove():獲取隊(duì)首的元素,并從隊(duì)列中移除element():獲取隊(duì)首的元素,但不從隊(duì)列中移除這一組,成功返回true,失敗時(shí)返回一個(gè)特殊值(取決于操作,為NULL或false),offer(E e)操作是專(zhuān)為容量受限的隊(duì)列實(shí)現(xiàn)而設(shè)計(jì)的;在大多數(shù)實(shí)現(xiàn)中,插入操作不會(huì)失敗。offer(E e):添加一個(gè)元素到隊(duì)尾poll():獲取隊(duì)首的元素,并從隊(duì)列中移除peek():獲取隊(duì)首的元素,但不從隊(duì)列中移除迭代器(Iterator)
迭代器是一種設(shè)計(jì)模式,它是一個(gè)對(duì)象,它可以遍歷并選擇序列中的對(duì)象,而開(kāi)發(fā)人員不需要了解該序列的底層結(jié)構(gòu)。迭代器通常被稱(chēng)為“輕量級(jí)”對(duì)象,因?yàn)閯?chuàng)建它的代價(jià)小。
Java中的Iterator功能比較簡(jiǎn)單,并且只能單向移動(dòng):
- ?使用方法iterator()要求容器返回一個(gè)Iterator。第一次調(diào)用Iterator的next()方法時(shí),它返回序列的第一個(gè)元素。注意:iterator()方法是java.lang.Iterable接口,被Collection繼承。
- hasNext():判斷當(dāng)前元素是否存在,并沒(méi)有指向的移動(dòng)
- next():返回當(dāng)前元素, 并指向下一個(gè)元素
- 使用remove()將迭代器新返回的元素刪除。
Iterator是Java迭代器最簡(jiǎn)單的實(shí)現(xiàn),為L(zhǎng)ist設(shè)計(jì)的ListIterator具有更多的功能,它可以從兩個(gè)方向遍歷List,也可以從List中插入和刪除元素。
樹(shù):
滿(mǎn)二叉樹(shù):除了葉節(jié)點(diǎn)外每一個(gè)結(jié)點(diǎn)都有左右子女且葉節(jié)點(diǎn)都處在最底層的二叉樹(shù)。
?
完全二叉樹(shù):只有最下面的兩層結(jié)點(diǎn)度小于2,并且最下面一層的結(jié)點(diǎn)都集中在該層最左邊的若干位置的二叉樹(shù)。
?
二叉樹(shù):查找最好O(logN),最差O(N),最差情況是所有的數(shù)據(jù)全部在一端時(shí)。
反轉(zhuǎn)二叉樹(shù)
if(root==null) return; else reverseTree(root); public void reverseTree(Node node){if(node.left!=null) reverseTree(node.left);if(node.right!=null) reverseTree(node.right);Node temp = node.right;node.right = node.left;node.left = temp; }二叉查找樹(shù):查找最好O(logN),最差O(N),最差情況是所有的數(shù)據(jù)全部在一端時(shí)
1.若任意結(jié)點(diǎn)的左子樹(shù)不空,則左子樹(shù)上所有結(jié)點(diǎn)的值均不大于它的根結(jié)點(diǎn)的值。
2. 若任意結(jié)點(diǎn)的右子樹(shù)不空,則右子樹(shù)上所有結(jié)點(diǎn)的值均不小于它的根結(jié)點(diǎn)的值。
3.任意結(jié)點(diǎn)的左、右子樹(shù)也分別為二叉搜索樹(shù)。
public class Node {public int index;//關(guān)鍵字段public String data;//值public Node leftNode;//左節(jié)點(diǎn)public Node rightNode;//右節(jié)點(diǎn) }//查找 public Node findNode(int key){Node current = root;while(current.index != key){if(key < current.index){//左節(jié)點(diǎn)current = current.leftNode;}else{//右節(jié)點(diǎn)current = current.rightNode;}if(current == null){return null;}}return current; }//插入 public void insertNode(int key,String value){Node node = new Node();node.index = key;node.data = value;if(root == null){root = node;return;}//找到插入節(jié)點(diǎn)的位置Node parent = root;Node current = root;while(true){parent = current;if(key == current.index){return;}if(key < current.index){//左節(jié)點(diǎn)current = current.leftNode;if(current == null){//當(dāng)前節(jié)點(diǎn)已經(jīng)是葉子結(jié)點(diǎn)了parent.leftNode = node; return;}}else{current = current.rightNode;if(current == null){parent.rightNode = node;return;}}} }平衡二叉樹(shù):又稱(chēng)為AVL樹(shù),查找O(logN),它是一顆空樹(shù)或它的左右兩個(gè)子樹(shù)的高度差的絕對(duì)值不超過(guò)1
哈夫曼樹(shù):帶權(quán)路徑長(zhǎng)度達(dá)到最小的二叉樹(shù),也叫做最優(yōu)二叉樹(shù)。
k層的二叉樹(shù),最多有節(jié)點(diǎn)個(gè)數(shù)為 2^k-1,最少有k個(gè)節(jié)點(diǎn)
第k層,最多有節(jié)點(diǎn)個(gè)數(shù)為 2^(k-1)個(gè)
紅黑樹(shù):查找刪除插入時(shí)間復(fù)雜度O(logN)
紅黑樹(shù)是每個(gè)節(jié)點(diǎn)都帶有顏色屬性的二叉查找樹(shù),顏色為紅色或黑色。在二叉查找樹(shù)強(qiáng)制的一般要求以外,對(duì)于任何有效的紅黑樹(shù)我們?cè)黾恿巳缦碌念~外要求:
前中后層遍歷
public void preOrder(Node root){ // 前序遍歷,"中左右"if (root != null){System.out.print(root.data + " ");preOrder(root.left);preOrder(root.right);}}public void inOrder(Node root){ // 中序遍歷,"左中右"if (root != null){inOrder(root.left);System.out.print(root.data + " ");inOrder(root.right);}}public void postOrder(Node root){ // 后序遍歷,"左右中"if (root != null){postOrder(root.left);postOrder(root.right);System.out.print(root.data + " ");}}public void floorOrder(Node root){if(root==null) return;Queue<Node> q = new LinkedBlockingQueue<>();q.add(root);while(!q.isEmpty()){Node t = q.poll();System.out.println(t.value);if(t.left!=null)q.add(t.left);if(t.right!=null)q.add(t.right);}}?
總結(jié)
以上是生活随笔為你收集整理的Java—Collection、Map、树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 科目三并不难 盘点科目三技巧
- 下一篇: Java—JVM加载机制