一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Java集合詳解【面試+工作】

 Java幫幫 2020-01-02

Java集合詳解【面試+提高】

在說(shuō)集合前我們不得不說(shuō)一下數(shù)組
數(shù)組的作用:

存放一組相同的數(shù)據(jù)類(lèi)型(基本或?qū)ο?的數(shù)據(jù),從而實(shí)現(xiàn)對(duì)數(shù)據(jù)的管理
優(yōu)勢(shì):可以快速的通過(guò)下標(biāo)對(duì)數(shù)組元素進(jìn)行訪問(wèn),效率高
劣勢(shì):容量實(shí)現(xiàn)定義好了,不能隨著需求變化而擴(kuò)容
因此出現(xiàn)了更好的集合框架

一、數(shù)組和集合的比較

數(shù)組不是面向?qū)ο蟮?,存在明顯的缺陷,集合彌補(bǔ)了數(shù)組的缺點(diǎn),比數(shù)組更靈活更實(shí)用,而且不同的集合框架類(lèi)可適用不同場(chǎng)合。如下:
1:數(shù)組能存放基本數(shù)據(jù)類(lèi)型和對(duì)象,而集合類(lèi)存放的都是對(duì)象的引用,而非對(duì)象本身!
2:數(shù)組容易固定無(wú)法動(dòng)態(tài)改變,集合類(lèi)容量動(dòng)態(tài)改變。 
3:數(shù)組無(wú)法判斷其中實(shí)際存有多少元素,length只告訴了數(shù)組的容量,而集合的size()可以確切知道元素的個(gè)數(shù) 
4:集合有多種實(shí)現(xiàn)方式和不同適用場(chǎng)合,不像數(shù)組僅采用順序表方式 
5:集合以類(lèi)的形式存在,具有封裝、繼承、多態(tài)等類(lèi)的特性,通過(guò)簡(jiǎn)單的方法和屬性即可實(shí)現(xiàn)各種復(fù)雜操作,大大提高了軟件的開(kāi)發(fā)效率

二、Java集合

此圖可用Windows系統(tǒng)自帶畫(huà)圖工具查看比較清晰

Collection和Map,是集合框架的根接口。

Collection的子接口:

Set:接口 ---實(shí)現(xiàn)類(lèi): HashSet、LinkedHashSet
   Set的子接口SortedSet接口---實(shí)現(xiàn)類(lèi):TreeSet
List:接口---實(shí)現(xiàn)類(lèi): LinkedList,Vector,ArrayList 


List集合

有序列表,允許存放重復(fù)的元素; 
實(shí)現(xiàn)類(lèi): 
ArrayList:數(shù)組實(shí)現(xiàn),查詢(xún)快,增刪慢,輕量級(jí);(線程不安全)
LinkedList:雙向鏈表實(shí)現(xiàn),增刪快,查詢(xún)慢 (線程不安全)
Vector:數(shù)組實(shí)現(xiàn),重量級(jí)  (線程安全、使用少)

ArrayList

底層是Object數(shù)組,所以ArrayList具有數(shù)組的查詢(xún)速度快的優(yōu)點(diǎn)以及增刪速度慢的缺點(diǎn)。

而在LinkedList的底層是一種雙向循環(huán)鏈表。在此鏈表上每一個(gè)數(shù)據(jù)節(jié)點(diǎn)都由三部分組成:前指針(指向前面的節(jié)點(diǎn)的位置),數(shù)據(jù),后指針(指向后面的節(jié)點(diǎn)的位置)。最后一個(gè)節(jié)點(diǎn)的后指針指向第一個(gè)節(jié)點(diǎn)的前指針,形成一個(gè)循環(huán)。

雙向循環(huán)鏈表的查詢(xún)效率低但是增刪效率高。

ArrayList和LinkedList在用法上沒(méi)有區(qū)別,但是在功能上還是有區(qū)別的。

LinkedList

LinkedList是采用雙向循環(huán)鏈表實(shí)現(xiàn)的。
利用LinkedList實(shí)現(xiàn)棧(stack)、隊(duì)列(queue)、雙向隊(duì)列(double-ended queue )。
它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()等。

經(jīng)常用在增刪操作較多而查詢(xún)操作很少的情況下:

隊(duì)列和堆棧。

隊(duì)列:先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)。

棧:后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)。

注意:使用棧的時(shí)候一定不能提供方法讓不是最后一個(gè)元素的元素獲得出棧的機(jī)會(huì)。

Vector

(與ArrayList相似,區(qū)別是Vector是重量級(jí)的組件,使用使消耗的資源比較多。)

結(jié)論:在考慮并發(fā)的情況下用Vector(保證線程的安全)。

在不考慮并發(fā)的情況下用ArrayList(不能保證線程的安全)。

ArrayList自動(dòng)擴(kuò)充機(jī)制
實(shí)現(xiàn)機(jī)制:ArrayList.ensureCapacity(int minCapacity)
首先得到當(dāng)前elementData 屬性的長(zhǎng)度oldCapacity。
然后通過(guò)判斷oldCapacity和minCapacity參數(shù)誰(shuí)大來(lái)決定是否需要擴(kuò)容, 如果minCapacity大于 
oldCapacity,那么我們就對(duì)當(dāng)前的List對(duì)象進(jìn)行擴(kuò)容。
擴(kuò)容的的策略為:取(oldCapacity * 3)/2 + 1和minCapacity之間更大的那個(gè)。然后使用數(shù)組拷 
貝的方法,把以前存放的數(shù)據(jù)轉(zhuǎn)移到新的數(shù)組對(duì)象中
如果minCapacity不大于oldCapacity那么就不進(jìn)行擴(kuò)容。


用LinkedList實(shí)現(xiàn)隊(duì)列:
隊(duì)列(Queue)是限定所有的插入只能在表的一端進(jìn)行,而所有的刪除都在表的另一端進(jìn)行的線性表。
表中允許插入的一端稱(chēng)為隊(duì)尾(Rear),允許刪除的一端稱(chēng)為隊(duì)頭(Front)。
隊(duì)列的操作是按先進(jìn)先出(FIFO)的原則進(jìn)行的。
隊(duì)列的物理存儲(chǔ)可以用順序存儲(chǔ)結(jié)構(gòu),也可以用鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。

用LinkedList實(shí)現(xiàn)棧:
棧(Stack)也是一種特殊的線性表,是一種后進(jìn)先出(LIFO)的結(jié)構(gòu)。
棧是限定僅在表尾進(jìn)行插入和刪除運(yùn)算的線性表,表尾稱(chēng)為棧頂(top),表頭稱(chēng)為棧底(bottom)。
棧的物理存儲(chǔ)可以用順序存儲(chǔ)結(jié)構(gòu),也可以用鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。

List常用方法:
void add(int index, Object element) :添加對(duì)象element到位置index上
boolean addAll(int index, Collection collection) :在index位置后添加容器collection中所有的元素
Object get(int index) :取出下標(biāo)為index的位置的元素
int indexOf(Object element) :查找對(duì)象element 在List中第一次出現(xiàn)的位置
int lastIndexOf(Object element) :查找對(duì)象element 在List中最后出現(xiàn)的位置
Object remove(int index) :刪除index位置上的元素 
ListIterator listIterator(int startIndex) :返回一個(gè)ListIterator 跌代器,開(kāi)始位置為startIndex 
List subList(int fromIndex, int toIndex) :返回一個(gè)子列表List ,元素存放為從 fromIndex 到toIndex之前的一個(gè)元素

Set集合

擴(kuò)展Collection接口
無(wú)序集合,不允許存放重復(fù)的元素;允許使用null元素
對(duì) add()、equals() 和 hashCode() 方法添加了限制
HashSet和TreeSet是Set的實(shí)現(xiàn)
Set—》hashSet linkedHashSet
SortedSet —》 TreeSet

HashSet 的后臺(tái)有一個(gè)HashMap;初始化后臺(tái)容量;只不過(guò)生成一個(gè)HashSet的話,系統(tǒng)只提供key的訪問(wèn); 如果有兩個(gè)Key重復(fù),那么會(huì)覆蓋之前的;

 
實(shí)現(xiàn)類(lèi) :
HashSet:equals返回true,hashCode返回相同的整數(shù);哈希表;存儲(chǔ)的數(shù)據(jù)是無(wú)序的。
LinkedHashSet:此實(shí)現(xiàn)與 HashSet 的不同之外在于,后者維護(hù)著一個(gè)運(yùn)行于所有條目的雙重鏈接列表。存儲(chǔ)的數(shù)據(jù)是有序的。

HashSet類(lèi)

HashSet類(lèi)直接實(shí)現(xiàn)了Set接口, 其底層其實(shí)是包裝了一個(gè)HashMap去實(shí)現(xiàn)的。HashSet采用HashCode算法來(lái)存取集合中的元素,因此具有比較好的讀取和查找性能。

HashSet的特征

  • 不僅不能保證元素插入的順序,而且在元素在以后的順序中也可能變化(這是由HashSet按HashCode存儲(chǔ)對(duì)象(元素)決定的,對(duì)象變化則可能導(dǎo)致HashCode變化)

  • HashSet是線程非安全的

  • HashSet元素值可以為NULL


HashSet常用方法:
public boolean contains(Object o) :如果set包含指定元素,返回true 
public Iterator iterator()返回set中元素的迭代器 
public Object[] toArray() :返回包含set中所有元素的數(shù)組public Object[] toArray(Object[] a) :返回包含set中所有元素的數(shù)組,返回?cái)?shù)組的運(yùn)行時(shí)類(lèi)型是指定數(shù)組的運(yùn)行時(shí)類(lèi)型
public boolean add(Object o) :如果set中不存在指定元素,則向set加入
public boolean remove(Object o) :如果set中存在指定元素,則從set中刪除 
public boolean removeAll(Collection c) :如果set包含指定集合,則從set中刪除指定集合的所有元素 
public boolean containsAll(Collection c) :如果set包含指定集合的所有元素,返回true。如果指定集合也是一個(gè)set,只有是當(dāng)前set的子集時(shí),方法返回true

實(shí)現(xiàn)Set接口的HashSet,依靠HashMap來(lái)實(shí)現(xiàn)的。
我們應(yīng)該為要存放到散列表的各個(gè)對(duì)象定義hashCode()和equals()。

HashSet的equals和HashCode

前面說(shuō)過(guò),Set集合是不允許重復(fù)元素的,否則將會(huì)引發(fā)各種奇怪的問(wèn)題。那么HashSet如何判斷元素重復(fù)呢?

HashSet需要同時(shí)通過(guò)equals和HashCode來(lái)判斷兩個(gè)元素是否相等,具體規(guī)則是,如果兩個(gè)元素通過(guò)equals為true,并且兩個(gè)元素的hashCode相等,則這兩個(gè)元素相等(即重復(fù))。

所以如果要重寫(xiě)保存在HashSet中的對(duì)象的equals方法,也要重寫(xiě)hashCode方法,重寫(xiě)前后hashCode返回的結(jié)果相等(即保證保存在同一個(gè)位置)。所有參與計(jì)算 hashCode() 返回值的關(guān)鍵屬性,都應(yīng)該用于作為 equals() 比較的標(biāo)準(zhǔn)。

試想如果重寫(xiě)了equals方法但不重寫(xiě)hashCode方法,即相同equals結(jié)果的兩個(gè)對(duì)象將會(huì)被HashSet當(dāng)作兩個(gè)元素保存起來(lái),這與我們?cè)O(shè)計(jì)HashSet的初衷不符(元素不重復(fù))。

另外如果兩個(gè)元素哈市Code相等但equals結(jié)果不為true,HashSet會(huì)將這兩個(gè)元素保存在同一個(gè)位置,并將超過(guò)一個(gè)的元素以鏈表方式保存,這將影響HashSet的效率。

如果重寫(xiě)了equals方法但沒(méi)有重寫(xiě)hashCode方法,則HashSet可能無(wú)法正常工作,比如下面的例子。

上面注釋了hashCode方法,所以你將會(huì)看到下面的結(jié)果。

false  

[R[count:9 # hashCode:14927396], R[count:5 # hashCode:24417480], R[count:-2 # hashCode:31817359], R[count:-3 # hashCode:13884241]]  

取消注釋?zhuān)瑒t結(jié)果就正確了 copy

true  

[R[count:5 # hashCode:5], R[count:9 # hashCode:9], R[count:-3 # hashCode:-3], R[count:-2 # hashCode:-2]]  


如何達(dá)到不能存在重復(fù)元素的目的?
“鍵”就是我們要存入的對(duì)象,“值”則是一個(gè)常量。這樣可以確保,我們所需要的存儲(chǔ)的信息
之是“鍵”。而“鍵”在Map中是不能重復(fù)的,這就保證了我們存入Set中的所有的元素都不重復(fù)。
HashSet如何過(guò)濾重復(fù)元素
調(diào)用元素HashCode獲得哈希碼--》判斷哈希碼是否相等,不相等則錄入
---》相等則判斷equals()后是否相等,不相等在進(jìn)行 hashcode錄入,相等不錄入

LinkedHashSet的特征

LinkedHashSet是HashSet的一個(gè)子類(lèi),LinkedHashSet也根據(jù)HashCode的值來(lái)決定元素的存儲(chǔ)位置,但同時(shí)它還用一個(gè)鏈表來(lái)維護(hù)元素的插入順序,插入的時(shí)候即要計(jì)算hashCode又要維護(hù)鏈表,而遍歷的時(shí)候只需要按鏈表來(lái)訪問(wèn)元素。查看LinkedHashSet的源碼發(fā)現(xiàn)它是樣的,

在JAVA7中, LinkedHashSet沒(méi)有定義任何方法,只有四個(gè)構(gòu)造函數(shù),它的構(gòu)造函數(shù)調(diào)用了父類(lèi)(HashSet)的帶三個(gè)參數(shù)的構(gòu)造方法,父類(lèi)的構(gòu)造函數(shù)如下,

由此可知,LinkedHashSet本質(zhì)上也是從LinkedHashMap而來(lái),LinkedHashSet的所有方法都繼承自HashSet, 而它能維持元素的插入順序的性質(zhì)則繼承自LinkedHashMap.

下面是一個(gè)LinkedHashSet維持元素插入順序的例子,

輸入如下

TreeSet類(lèi)的特征

TreeSet實(shí)現(xiàn)了SortedSet接口,顧名思義這是一種排序的Set集合,查看jdk源碼發(fā)現(xiàn)底層是用TreeMap實(shí)現(xiàn)的,本質(zhì)上是一個(gè)紅黑樹(shù)原理。 正因?yàn)樗桥判蛄说?,所以相?duì)HashSet來(lái)說(shuō),TreeSet提供了一些額外的按排序位置訪問(wèn)元素的方法,例如first(), last(), lower(), higher(), subSet(), headSet(), tailSet().

TreeSet的排序分兩種類(lèi)型,一種是自然排序,另一種是定制排序。

自然排序(在元素中寫(xiě)排序規(guī)則)

TreeSet 會(huì)調(diào)用compareTo方法比較元素大小,然后按升序排序。所以自然排序中的元素對(duì)象,都必須實(shí)現(xiàn)了Comparable接口,否則會(huì)跑出異常。對(duì)于TreeSet判斷元素是否重復(fù)的標(biāo)準(zhǔn),也是調(diào)用元素從Comparable接口繼承而來(lái)額compareTo方法,如果返回0則是重復(fù)元素(兩個(gè)元素I相等)。Java的常見(jiàn)類(lèi)都已經(jīng)實(shí)現(xiàn)了Comparable接口,下面舉例說(shuō)明沒(méi)有實(shí)現(xiàn)Comparable存入TreeSet時(shí)引發(fā)異常的情況。

運(yùn)行程序會(huì)拋出如下異常

將上面的Err類(lèi)實(shí)現(xiàn)Comparable接口之后程序就能正常運(yùn)行了

還有個(gè)重要問(wèn)題是,因?yàn)門(mén)reeSet會(huì)調(diào)用元素的compareTo方法,這就要求所有元素的類(lèi)型都相同,否則也會(huì)發(fā)生異常。也就是說(shuō),TreeSet只允許存入同一類(lèi)的元素。例如下面這個(gè)例子就會(huì)拋出類(lèi)型轉(zhuǎn)換異常

運(yùn)行結(jié)果


定制排序(在集合中寫(xiě)排序規(guī)則)

TreeSet還有一種排序就是定制排序,定制排序時(shí)候,需要關(guān)聯(lián)一個(gè) Comparator對(duì)象,由Comparator提供排序邏輯。下面就是一個(gè)使用Lambda表達(dá)式代替Comparator對(duì)象來(lái)提供定制排序的例子。 下面是一個(gè)定制排序的列子

當(dāng)然將Comparator直接寫(xiě)入TreeSet初始化中也可以。如下。

TreeSet是依靠TreeMap來(lái)實(shí)現(xiàn)的。
TreeSet是一個(gè)有序集合,TreeSet中元素將按照升序排列,缺省是按照自然順序進(jìn)行排列,意味著TreeSet中元素要實(shí)現(xiàn)Comparable接口
我們可以在構(gòu)造TreeSet對(duì)象時(shí),傳遞實(shí)現(xiàn)了Comparator接口的比較器對(duì)象。

Comparable和Comparator 
Comparable 接口以提供自然排序順序。
對(duì)于那些沒(méi)有自然順序的類(lèi)、或者當(dāng)您想要一個(gè)不同于自然順序的順序時(shí),您可以實(shí)現(xiàn) 
Comparator 接口來(lái)定義您自己的排序函數(shù)??梢詫omparator傳遞給Collections.sort或Arrays.sort。

Comparator接口 
當(dāng)一個(gè)類(lèi)并未實(shí)現(xiàn)Comparable,或者不喜歡缺省的Comaparable行為??梢詫?shí)現(xiàn)Comparator接口
直接實(shí)現(xiàn)Comparator的compare接口完成自定義比較類(lèi)。
例:Arrays.sort(results, new Comparator<RepDataQueryResultVO>() 數(shù)組排序 RepDataQueryExecutor
例:Collections.sort(lst,new Comparator<TaskPrintSchemeVO>()

EnumSet特征

EnumSet顧名思義就是專(zhuān)為枚舉類(lèi)型設(shè)計(jì)的集合,因此集合元素必須是枚舉類(lèi)型,否則會(huì)拋出異常。 EnumSet集合也是有序的,其順序就是Enum類(lèi)內(nèi)元素定義的順序。EnumSet存取的速度非常快,批量操作的速度也很快。EnumSet主要提供以下方法,allOf, complementOf, copyOf, noneOf, of, range等。注意到EnumSet并沒(méi)有提供任何構(gòu)造函數(shù),要?jiǎng)?chuàng)建一個(gè)EnumSet集合對(duì)象,只需要調(diào)用allOf等方法,下面是一個(gè)EnumSet的例子。

執(zhí)行結(jié)果


幾種Set的比較:
HashSet外部無(wú)序地遍歷成員。 
成員可為任意Object子類(lèi)的對(duì)象,但如果覆蓋了equals方法,同
時(shí)注意修改hashCode方法。 
TreeSet外部有序地遍歷成員; 
附加實(shí)現(xiàn)了SortedSet, 支持子集等要求順序的操作 
成員要求實(shí)現(xiàn)Comparable接口,或者使用Comparator構(gòu)造
TreeSet。成員一般為同一類(lèi)型。 
LinkedHashSet外部按成員的插入順序遍歷成員 
成員與HashSet成員類(lèi)似 
HashSet是基于Hash算法實(shí)現(xiàn)的,其性能通常都優(yōu)于TreeSet。我們通常都應(yīng)該使用HashSet,在我們需要排序的功能時(shí),我們才使用TreeSet。

HashSet的元素存放順序和我們添加進(jìn)去時(shí)候的順序沒(méi)有任何關(guān)系,而LinkedHashSet 則保持元素的添加順序。TreeSet則是對(duì)我們的Set中的元素進(jìn)行排序存放。

一般來(lái)說(shuō),當(dāng)您要從集合中以有序的方式抽取元素時(shí),TreeSet 實(shí)現(xiàn)就會(huì)有用處。為了能順利進(jìn)行,添加到 TreeSet 的元素必須是可排序的。 而您同樣需要對(duì)添加到TreeSet中的類(lèi)對(duì)象實(shí)現(xiàn) Comparable 接口的支持。一般說(shuō)來(lái),先把元素添加到 HashSet,再把集合轉(zhuǎn)換為 TreeSet 來(lái)進(jìn)行有序遍歷會(huì)更快。

各種Set集合性能分析

  • HashSet和TreeSet是Set集合中用得最多的I集合。HashSet總是比TreeSet集合性能好,因?yàn)镠ashSet不需要額維護(hù)元素的順序。

  • LinkedHashSet需要用額外的鏈表維護(hù)元素的插入順序,因此在插入時(shí)性能比HashSet低,但在迭代訪問(wèn)(遍歷)時(shí)性能更高。因?yàn)椴迦氲臅r(shí)候即要計(jì)算hashCode又要維護(hù)鏈表,而遍歷的時(shí)候只需要按鏈表來(lái)訪問(wèn)元素。

  • EnumSet元素是所有Set元素中性能最好的,但是它只能保存Enum類(lèi)型的元素

Map

集合框架的第二類(lèi)接口樹(shù)。
它提供了一組鍵值的映射。其中存儲(chǔ)的每個(gè)對(duì)象都有一個(gè)相應(yīng)的關(guān)鍵字(key),關(guān)鍵字決定了對(duì)象在Map中的存儲(chǔ)位置。
關(guān)鍵字應(yīng)該是唯一的,每個(gè)key 只能映射一個(gè)value。

實(shí)現(xiàn)類(lèi):

HashMap、TreeMap、LinkedHashMap、Hashtable等
HashMap:鍵值對(duì),key不能重復(fù),但是value可以重復(fù);key的實(shí)現(xiàn)就是HashSet;value對(duì)應(yīng)著放;允許null的鍵或值;
Hashtable:線程安全的,不允許null的鍵或值;
Properties::key和value都是String類(lèi)型,用來(lái)讀配置文件;
TreeMap:對(duì)key排好序的Map; key 就是TreeSet, value對(duì)應(yīng)每個(gè)key; key要實(shí)現(xiàn)Comparable接口或TreeMap有自己的構(gòu)造器; 
LinkedHashMap: 此實(shí)現(xiàn)與 HashMap 的不同之處在于,后者維護(hù)著一個(gè)運(yùn)行于所有條目的雙重鏈接列表。存儲(chǔ)的數(shù)
據(jù)是有序的。


HashMap:
Map 主要用于存儲(chǔ)鍵(key)值(value)對(duì),根據(jù)鍵得到值,因此鍵不允許重復(fù),但允許值重復(fù)。
HashMap 是一個(gè)最常用的Map,它根據(jù)鍵的HashCode 值存儲(chǔ)數(shù)據(jù),根據(jù)鍵可以直接獲取它的值,具有很快的訪問(wèn)速度。
HashMap最多只允許一條記錄的鍵為Null;允許多條記錄的值為 Null;
HashMap不支持線程的同步,即任一時(shí)刻可以有多個(gè)線程同時(shí)寫(xiě)HashMap;可能會(huì)導(dǎo)致數(shù)據(jù)的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力。

HashMap實(shí)現(xiàn)原理---散列
Hash哈希算法的意義在于提供了一種快速存取數(shù)據(jù)的方法,它用一種算法建立鍵值與真實(shí)值之間的對(duì)應(yīng)關(guān)系。散列表又稱(chēng)為哈希表。散列表算法的基本思想是:以結(jié)點(diǎn)的關(guān)鍵字為自變量,通過(guò)一定的函數(shù)關(guān)系(散列函數(shù))計(jì)算出對(duì)應(yīng)的函數(shù)值,以這個(gè)值作為該結(jié)點(diǎn)存儲(chǔ)在散列表中地址。
當(dāng)散列表中的元素存放太滿(mǎn),就必須進(jìn)行再散列,將產(chǎn)生一個(gè)新的散列表,所有元素存放到新的散列表中,原先的散列表將被刪除。在Java語(yǔ)言中,通過(guò)負(fù)載因子(load factor)來(lái)決定何時(shí)對(duì)散列表進(jìn)行再散列。例如:如果負(fù)載因子0.75,當(dāng)散列表中已經(jīng)有75%位置已經(jīng)放滿(mǎn),那么將進(jìn)行再散列。
負(fù)載因子越高(越接近1.0),內(nèi)存的使用效率越高,元素的尋找時(shí)間越長(zhǎng)。負(fù)載因子越低(越接近0.0),元素的尋找時(shí)間越短,內(nèi)存浪費(fèi)越多。

何時(shí)需重寫(xiě)equals?
當(dāng)一個(gè)類(lèi)有自己特有的“邏輯相等”概念(不同于對(duì)象身份的概念);
Object類(lèi)僅僅提供了一個(gè)對(duì)引用的比較,如果兩個(gè)引用不是同一個(gè)那就返回false,這是無(wú)法滿(mǎn)足大多數(shù)對(duì)象比較的需要的,所以要覆蓋;
使用==操作符檢查實(shí)參是否為指向?qū)ο蟮囊谩?/span>
使用instanceof操作符檢查實(shí)參是否為正確的類(lèi)型
把實(shí)參轉(zhuǎn)換到正確的類(lèi)型;
對(duì)于該類(lèi)中每一個(gè)“關(guān)鍵”域,檢查實(shí)參中的域與當(dāng)前對(duì)象中對(duì)應(yīng)的域值是否匹 配。對(duì)于既不是float也不是double類(lèi)型的基本類(lèi)型的域,可以使用==操作符 進(jìn)行比較;對(duì)于對(duì)象引用類(lèi)型的域,可以遞歸地調(diào)用所引用的對(duì)象的equals方法,對(duì)于float和double類(lèi)型的域,先轉(zhuǎn)換成int或long類(lèi)型的值,然后使用==操作符比較;
當(dāng)你編寫(xiě)完成了equals方法之后,應(yīng)該問(wèn)自己三個(gè)問(wèn)題:它是否是對(duì)稱(chēng)的、傳 遞的、一致的? 如果答案是否定的,那么請(qǐng)找到 這些特性未能滿(mǎn)足的原因,再修改equals方法的代碼

equals()和hashCode()同時(shí)覆寫(xiě)
尤其強(qiáng)調(diào)當(dāng)一個(gè)對(duì)象被當(dāng)作鍵值(或索引)來(lái)使用的時(shí)候要重寫(xiě)這兩個(gè)方法;
覆寫(xiě)equals后,兩個(gè)不同實(shí)例可能在邏輯上相等,但是根據(jù)Object.hashCode方法卻產(chǎn)生不同的散列碼,違反“相等的對(duì)象必須具有相等的散列碼”。
導(dǎo)致,當(dāng)你用其中的一個(gè)作為鍵保存到hashMap、hasoTable或hashSet中,再以“相等的”找另 一個(gè)作為鍵值去查找他們的時(shí)候,則根本找不到
不同類(lèi)型的hashCode取值
如果該域是布爾型的,計(jì)算(f?0:1)
如果是char,short,byte或int,計(jì)算(int)f
如果是long類(lèi)型,計(jì)算(int)(f^(f>>>32))
如果是float類(lèi)型,計(jì)算Float.floatToIntBits(f)
如果是double類(lèi)型,計(jì)算Dobule.doubleToLongBits(f)
如果該域是一個(gè)對(duì)象引用,遞歸調(diào)用hashCode
如果該域是一個(gè)數(shù)組,則把每個(gè)元素當(dāng)做單獨(dú)的域來(lái)處理,對(duì)每個(gè)重要的元素計(jì)算一個(gè)散列碼,


Map集合比較:
HashMap的存入順序和輸出順序無(wú)關(guān)。
LinkedHashMap 則保留了鍵值對(duì)的存入順序。
TreeMap則是對(duì)Map中的元素進(jìn)行排序。
因?yàn)镠ashMap和LinkedHashMap 存儲(chǔ)數(shù)據(jù)的速度比直接使用TreeMap 要快,存取效率要高。
當(dāng)完成了所有的元素的存放后,我們?cè)賹?duì)整個(gè)的Map中的元素進(jìn)行排序。這樣可以提高整個(gè)程序的運(yùn)行的效率,縮短執(zhí)行時(shí)間。
注意:TreeMap中是根據(jù)鍵(Key)進(jìn)行排序的。而如果我們要使用TreeMap來(lái)進(jìn)行正常的排序的話,Key 中存放的對(duì)象必須實(shí)現(xiàn)Comparable 接口。

Map常用方法:
Object put(Object key,Object value):用來(lái)存放一個(gè)鍵-值對(duì)Map中 
Object remove(Object key):根據(jù)key(鍵),移除鍵-值對(duì),并將值返回
void putAll(Map mapping) :將另外一個(gè)Map中的元素存入當(dāng)前的Map中
void clear() :清空當(dāng)前Map中的元素
Object get(Object key) :根據(jù)key(鍵)取得對(duì)應(yīng)的值
boolean containsKey(Object key) :判斷Map中是否存在某鍵(key)
boolean containsValue(Object value):判斷Map中是否存在某值(value) 
public Set keySet() :返回所有的鍵(key),并使用Set容器存放
public Collection values() :返回所有的值(Value),并使用Collection存放
public Set entrySet() :返回一個(gè)實(shí)現(xiàn) Map.Entry 接口的元素 Set

集合遍歷

1、增強(qiáng)for循環(huán) for(Obj o:c){syso(o)}
2、使用iterator , Iterator it=c.iterator;
          while(it.hasNext()){Object o = it.next()}
3、普通循環(huán):for(Iterator it=c.iterator();it.hasNext();){it.next() }

代碼實(shí)例

總結(jié)與面試

1.ArrayList: 元素單個(gè),效率高,多用于查詢(xún)

2.Vector:    元素單個(gè),線程安全,多用于查詢(xún)

3.LinkedList:元素單個(gè),多用于插入和刪除

4.HashMap:   元素成對(duì),元素可為空

5.HashTable: 元素成對(duì),線程安全,元素不可為空

HashMap和Hashtable的區(qū)別:

HashMap和Hashtable都是java的集合類(lèi),都可以用來(lái)存放java對(duì)象,這是他們的相同點(diǎn)

以下是他們的區(qū)別:

1.歷史原因:

Hashtable是基于陳舊的Dictionary類(lèi)的,HashMap是java 1.2引進(jìn)的Map接口的一個(gè)現(xiàn)實(shí)。

2.同步性:

Hashtable是同步的,這個(gè)類(lèi)中的一些方法保證了Hashtable中的對(duì)象是線程安全的,而HashMap則是異步的,因此HashMap中的對(duì)象并不是線程安全的,因?yàn)橥降囊髸?huì)影響執(zhí)行的效率,所以如果你不需要線程安全的結(jié)合那么使用HashMap是一個(gè)很好的選擇,這樣可以避免由于同步帶來(lái)的不必要的性能開(kāi)銷(xiāo),從而提高效率,我們一般所編寫(xiě)的程序都是異步的,但如果是服務(wù)器端的代碼除外。

3.值:

HashMap可以讓你將空值作為一個(gè)表的條目的key或value

Hashtable是不能放入空值(null)的

ArrayList和Vector的區(qū)別:

ArrayList與Vector都是java的集合類(lèi),都是用來(lái)存放java對(duì)象,這是他們的相同點(diǎn),

區(qū)別:

1.同步性:

Vector是同步的,這個(gè)類(lèi)的一些方法保證了Vector中的對(duì)象的線程安全的,而ArrayList則是異步的,因此ArrayList中的對(duì)象并不 是線程安全的,因?yàn)橥揭髸?huì)影響執(zhí)行的效率,所以你不需要線程安全的集合那么使用ArrayList是一個(gè)很好的選擇,這樣可以避免由于同步帶來(lái)的不必 要的性能開(kāi)銷(xiāo)。

2.數(shù)據(jù)增長(zhǎng):

從內(nèi)部實(shí)現(xiàn)的機(jī)制來(lái)講,ArrayList和Vector都是使用數(shù)組(Array)來(lái)控制集合中的對(duì)象,當(dāng)你向兩種類(lèi)型中增加元素的時(shí)候,如果元素的數(shù)目超過(guò)了內(nèi)部數(shù)組目前的長(zhǎng)度他們都需要擴(kuò)展內(nèi)部數(shù)組的長(zhǎng)度,Vector缺省情況下自動(dòng)增長(zhǎng)原來(lái)一倍的數(shù)組長(zhǎng)度,ArrayList是原來(lái)的50%,所以最后你獲得的這個(gè)集合所占的空間總是比你實(shí)際需要的要大,所以如果你要在集合中保存大量的數(shù)據(jù),那么使用Vector有一些優(yōu)勢(shì),因?yàn)槟憧梢酝ㄟ^(guò)設(shè)置集合的初始大小來(lái)避免不必要的資源開(kāi)銷(xiāo)。

總結(jié):

1)如果要求線程安全,使用Vector,Hashtable

2)如果不要求線程安全,使用ArrayList,LinkedList,HashMap

3)如果要求鍵值對(duì),則使用HashMap,Hashtable

4)如果數(shù)據(jù)量很大,又要求線程安全考慮Vector

arraylist和linkedlist聯(lián)系與區(qū)別
1.ArrayList是實(shí)現(xiàn)了基于動(dòng)態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)。
2.對(duì)于隨機(jī)訪問(wèn)get和set,ArrayList覺(jué)得優(yōu)于LinkedList,因?yàn)長(zhǎng)inkedList要移動(dòng)指針。
3.對(duì)于新增和刪除操作add和remove,LinedList比較占優(yōu)勢(shì),因?yàn)锳rrayList要移動(dòng)數(shù)據(jù)。 這一點(diǎn)要看實(shí)際情況的。若只對(duì)單條數(shù)據(jù)插入或刪除,ArrayList的速度反而優(yōu)于LinkedList。但若是批量隨機(jī)的插入刪除數(shù)據(jù),LinkedList的速度大大優(yōu)于ArrayList. 因?yàn)锳rrayList每插入一條數(shù)據(jù),要移動(dòng)插入點(diǎn)及之后的所有數(shù)據(jù)。

HashMap與TreeMap聯(lián)系與區(qū)別
1、 HashMap通過(guò)hashcode對(duì)其內(nèi)容進(jìn)行快速查找,而TreeMap中所有的元素都保持著某種固定的順序,如果你需要得到一個(gè)有序的結(jié)果你就應(yīng)該使用TreeMap(HashMap中元素的排列順序是不固定的)。
2、在Map 中插入、刪除和定位元素,HashMap是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那么TreeMap會(huì)更好。使用HashMap要求添加的鍵類(lèi)明確定義了hashCode()和 equals()的實(shí)現(xiàn)。
兩個(gè)map中的元素一樣,但順序不一樣,導(dǎo)致hashCode()不一樣。

同樣做測(cè)試:
在HashMap中,同樣的值的map,順序不同,equals時(shí),false;
而在treeMap中,同樣的值的map,順序不同,equals時(shí),true,說(shuō)明,treeMap在equals()時(shí)是整理了順序了的。

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多

    欧美中文字幕一区在线| 男人操女人下面国产剧情| 久久偷拍视频免费观看| 91久久精品在这里色伊人| 欧美丰满大屁股一区二区三区| 国产成人精品视频一二区| 一区二区三区人妻在线| 亚洲视频偷拍福利来袭| 麻豆在线观看一区二区| 亚洲国产精品久久综合网 | 韩国激情野战视频在线播放| 熟女高潮一区二区三区| 国产三级不卡在线观看视频| 99国产精品国产精品九九| 国产精品国产亚洲看不卡| 国产一级特黄在线观看| 亚洲人午夜精品射精日韩| 日本办公室三级在线观看| 午夜资源在线观看免费高清| 亚洲中文字幕人妻系列| 日本一本在线免费福利| 激情图日韩精品中文字幕| 中文字幕亚洲精品乱码加勒比| 免费高清欧美一区二区视频| 激情视频在线视频在线视频| 欧美日韩国产免费看黄片| 亚洲国产日韩欧美三级| 91久久国产福利自产拍| 成人精品一区二区三区综合| 99久久精品一区二区国产| 激情三级在线观看视频| 精品推荐国产麻豆剧传媒| 字幕日本欧美一区二区| 日本精品中文字幕在线视频| 东京不热免费观看日本| 国产肥妇一区二区熟女精品| 欧美人妻盗摄日韩偷拍| 91老熟妇嗷嗷叫太91| 黄色av尤物白丝在线播放网址| 亚洲综合激情另类专区老铁性| 欧美日韩精品综合一区|