集合概览
在網(wǎng)上找了個(gè)集合類圖,在此表示感謝原作者:
1.Set
Set集合不允許包含相同的元素,如果試圖把兩個(gè)相同元素加入同一個(gè)集合中,add方法返回false。
Set判斷兩個(gè)對(duì)象相同不是使用==運(yùn)算符,只要兩個(gè)對(duì)象用equals方法比較返回true就是重復(fù)。
從Java源碼來(lái)看,Java是先實(shí)現(xiàn)了Map,然后通過(guò)包裝一個(gè)value都為null的Map就實(shí)現(xiàn)了Set集合。
1.1 HashSet
HashSet集合中,當(dāng)hashCode()返回值相等,且equals()方法也相等的兩個(gè)元素才叫重復(fù)。
HashSet速度快的原因:
hash算法的價(jià)值在于速度,當(dāng)需要查詢集合中某個(gè)元素時(shí),hash算法可直接根據(jù)該元素的hashcode值計(jì)算出該元素的存儲(chǔ)位置
HashSet特性:
不是線程同步的
不能保證元素的插入順序,順序有可能發(fā)生變化
存儲(chǔ)的元素可以是null,但只能放入一個(gè)null
1.2 TreeSet
TreeSet支持兩種排序方式,自然排序 和定制排序。
自然排序(默認(rèn)排序方式):
使用要排序元素的CompareTo(Object obj)方法來(lái)比較元素之間大小關(guān)系,然后將元素按升序排列。如:
obj1.compareTo(obj2)方法如果返回0,則說(shuō)明被比較的兩個(gè)對(duì)象相等,如果返回一個(gè)正數(shù),則表明obj1大于obj2,如果是 負(fù)數(shù),則表明obj1小于obj2。
TreeSet判斷兩個(gè)對(duì)象是否相等的唯一標(biāo)準(zhǔn)是:這兩個(gè)對(duì)象的compareTo方法返回結(jié)果為0
定制排序:
參考:http://blog.csdn.net/zcl_love_wx/article/details/60757075
注:
TreeSet在添加第一個(gè)元素時(shí),由于不會(huì)與其他任何元素進(jìn)行比較,所以不會(huì)實(shí)現(xiàn)Comparable接口,只有在添加后續(xù)的元素時(shí),才會(huì)實(shí)現(xiàn)Comparable接口,然后調(diào)用compareTo方法比較,然后按升序排列。
如果希望TreeSet能正常運(yùn)作,所有元素只能是同一種數(shù)據(jù)類型。
1.3 LinkedHashSet
1.4 總結(jié)
只有當(dāng)一個(gè)集合需要保持順序時(shí),才應(yīng)該用TreeSet,否則都應(yīng)該用HashSet
2. List
List判斷兩個(gè)對(duì)象的相等條件是,equals()方法的返回值為true
2.1 ArrayList和Vector幾個(gè)常見(jiàn)方法
addAll(int index,Collection c):將集合c插入到List集合的index索引處
set(int index,Object o):將集合中index索引處的元素替換為o,并返回舊元素。
subList(int from,int to):返回從from到to(不包含)的子集合。
其實(shí)大多數(shù)截取從一個(gè)索引到另一個(gè)索引的所有值,都是不包含后一個(gè)索引的值的。最初我一直記不清楚,后來(lái)發(fā)現(xiàn),如果兩個(gè)索引的值都包含的話,我們將永遠(yuǎn)不能做到只取一個(gè)值的情況。
replaceAll(UnaryPerator uo):根據(jù)uo指定的計(jì)算規(guī)則,重新設(shè)置List集合
sort(Comparator c):根據(jù)自定義的比較器指定的計(jì)算規(guī)則對(duì)List排序。
2.2 ArrayList和Vector集合的listIterator()方法返回一個(gè)ListIterator對(duì)象,擴(kuò)展了操作集合的方法:
hasPrevious():是否有上一個(gè)元素
previous():返回上一個(gè)元素
add(String e):添加一個(gè)元素。Iterator就不可以。
ListIterator和Iterator都有hasNext()和next()方法,可以實(shí)現(xiàn)順序向后遍歷。但是ListIterator有hasPrevious()和previous()方法,可以實(shí)現(xiàn)逆向(順序向前)遍歷。nextIndex()和previousIndex()方法可以定位當(dāng)前元素的索引位置。Iterator就不可以。
2.3 ArrayList、Vector、LinkedList的區(qū)別
2.4 Stack類
Stack繼承自Vector,實(shí)現(xiàn)一個(gè)后進(jìn)先出的堆棧。Stack提供5個(gè)額外的方法使得Vector得以被當(dāng)作堆棧使用。
peek():返回棧頂?shù)谝辉?#xff0c;但并不彈出。
pop():返回棧頂?shù)谝粋€(gè)元素,并彈出。
push(Object o):將元素加入棧頂。
empty方法測(cè)試堆棧是否為空
search方法檢測(cè)一個(gè)元素在堆棧中的位置。
Stack剛創(chuàng)建后是空棧。
2.5 固定長(zhǎng)度的List
Arrays類的asList(Object … a)方法,可以將一個(gè)數(shù)組轉(zhuǎn)成一個(gè)List集合,而該集合既不是ArrayList的實(shí)現(xiàn)類,也不是Vector的,而是Arrays的內(nèi)部類ArrayList的實(shí)例。Arrays.ArrayList是一個(gè)固定長(zhǎng)度的List集合,程序只能遍歷該集合,不能進(jìn)行增、刪操作。
2.6 使用List集合建議
對(duì)于ArrayList 和Vector集合使用get(i)遍歷
對(duì)于LinkedList集合使用Iterator遍歷
3. Queue集合
4. 線性表性能分析
數(shù)組是以一塊連續(xù)內(nèi)存區(qū)來(lái)保存所有元素的容器。對(duì)于所有內(nèi)部基于數(shù)組的集合實(shí)現(xiàn)(如ArrayList、Vector),使用隨機(jī)訪問(wèn)的性能比使用Iterator迭代訪問(wèn)要好,因?yàn)殡S機(jī)訪問(wèn)會(huì)被映射成對(duì)數(shù)組的訪問(wèn)。但插入和刪除數(shù)據(jù)時(shí)涉及到數(shù)組元素移動(dòng)等內(nèi)存操作,所以相對(duì)來(lái)說(shuō)就慢。
5. 操作集合的工具類:Collections
5.1 對(duì)List集合元素進(jìn)行排序
reverse(List list) 反轉(zhuǎn)指定的list集合
sort(List list) 按自然排序?qū)ist排序
sort(List list,Comparator c) 按排序器c指定的規(guī)則將list進(jìn)行排序
swap(List list ,int i , int j) 將list集合中索引為i與j的元素對(duì)調(diào)交換
5.2 查找、替換的方法
int binarySearch(List list, Object key):二分法搜索key對(duì)應(yīng)的元素在list里的索引。前提是list已經(jīng)有序。
Object max(Collection c):返回集合中最大元素。按自然排序的結(jié)果。返回最小元素一樣。
Object max(Collection c,Comparator comp):按給定的排序規(guī)則返回最大元素。返回最小元素一樣。
void fill(List list,Object obj):用obj替換list的所有元素
int frequency(Collection c,Object o):o在c中出現(xiàn)的次數(shù)
int indexOfSubList(List source,List target):返回target子集在source中第1次出現(xiàn)的索引,沒(méi)有返回-1
int lastIndexOfSubList()List source,List target):返回target子集在source中最后一次出現(xiàn)的索引,沒(méi)有返回-1
boolean replaceAll(List list,Object oldVal,Object newVal):用newVal替換list中的所有oldVal
5.3 同步控制:SynchronizedXxx()方法
Java集合中,HashSet、TreeSet、HashMap、TreeMap、ArrayList、LinkedList、ArrayDeque等 都是線程不安全的,可通過(guò)SynchronizedXxx方法包裝成線程安全的集合,如:
Collection c = Collections.synchronizedCollection(new ArrayList<>()); List list = Collections.synchronizedList(new ArrayList()); Set set = Collections.synchronizedSet(new HashSet()); Map map = Collections.synchronizedMap(new HashMap<>());6. Map
6.1. Map常見(jiàn)方法
keySet():返回Map集合里所有key組成的Set集合
entrySet():返回Map中所有Entry對(duì)象組成的set集合,Entry是Map的內(nèi)部類。
forEach(BiConsumer action):Java8新增遍歷Map的方法
6.2. Entry這個(gè)內(nèi)部類,封裝了一個(gè)key-value對(duì),介紹其如下三個(gè)方法:
Object getKey():返回Entry里包含的key值
Object getValue():返回Entry里包含的value值
Object setValue(V value):設(shè)置Entry里包含的value,并返回新設(shè)的值
6.3 TreeMap
如果程序需要一個(gè)總是排好序的Map時(shí),則應(yīng)該考慮用TreeMap
TreeMap和TreeSet有很多類似之處
6.4 HashMap
6.5LinkedHashMap
LinkedHashMap也使用雙端鏈表來(lái)維護(hù)key-value對(duì)的次序,和linkedHashSet一樣也維護(hù)了插入順序,所以迭代也快。
6.6 WeakHashMap
WeakHashMap中只保留了對(duì)實(shí)際對(duì)象的弱引用;
如果WeakHashMap中的key所引用的對(duì)象沒(méi)有被其他強(qiáng)引用變量所引用,則這些key所引用的對(duì)象可能被垃圾回收,WeakHashMap也可以自動(dòng)刪除這些key所對(duì)應(yīng)的key-value對(duì)。
6.7 Properties
Properties相當(dāng)于一個(gè)key、value都為String類型的Map
Properties類可以把鍵值對(duì)和屬性文件關(guān)聯(lián)起來(lái),從而可以key-value對(duì)寫入屬性文件,也可以把屬性文件中的”屬性名=屬性值”加載到Properties對(duì)象中。
Properties修改key、value的方法:
String getProperty(String key ):獲取Properties中key對(duì)應(yīng)的value
setProperty(String key,String value):給Properties設(shè)置鍵和值
讀寫屬性文件的方法:
void load(InputStream in):從屬性文件中加載所有key-value對(duì)到Properties里
void store(OutPutStream out, String comments):將Properties中的key-value對(duì)輸出到指定的屬性文件中
示例:
Properties outP = new Properties(); outP.setProperty("username", "peter"); outP.setProperty("password", "123456"); //將兩個(gè)key-value對(duì)添加到a.txt屬性文件中 outP.store(new FileOutputStream("a.txt"), "備注信息");Properties inP = new Properties(); //將屬性文件加載到Properties里 inP.load(new FileInputStream("a.txt")); System.out.println(inP.getProperty("username"));6.8 Map性能分析
HashMap是為快速查詢?cè)O(shè)計(jì)的,其實(shí)現(xiàn)原理是利用key的hash值快速定位到value值在hash表的位置。但HashMap底層是采用數(shù)組來(lái)存儲(chǔ)key-value對(duì)。所以在使用containsKey(Object key)或containsValue(Object val)時(shí)只能通過(guò)遍歷數(shù)組來(lái)查詢。
TreeMap存儲(chǔ)數(shù)組的結(jié)構(gòu)是二叉樹,所以在使用containsKey(Object key)或containsValue(Object val)時(shí)都是二分查詢,要快于HashMap的這兩個(gè)操作。
Hash表里可以存儲(chǔ)元素的位置被稱為桶(bucket)。通常桶里只存一個(gè)元素,此時(shí)有最好的性能。hash算法可根據(jù)hashCode值計(jì)算出“桶”的存儲(chǔ)位置,接著從桶中取出元素。當(dāng)發(fā)生hash沖突時(shí),一個(gè)桶會(huì)存儲(chǔ)多個(gè)元素,它們以鏈表形式存儲(chǔ),且必須安順序搜索。
hash屬性:
1. 容量:hash表中桶的數(shù)量
2. 尺寸:當(dāng)前hash表中記錄的數(shù)量
3.負(fù)載因子:尺寸/容量。為0時(shí) 表示空hash表;為0.5時(shí) 表示半滿的hash表
輕負(fù)載的hash表沖突少,適宜插入、查詢,但用Iterator迭代慢。
較高的負(fù)載極限可降低hash所占內(nèi)存空間,但會(huì)增加查詢時(shí)間。
默認(rèn)負(fù)載極限為:0.75
7. Java 并發(fā)工具包 java.util.concurrent
總結(jié)
- 上一篇: mysql计算某一天所在周或月的第一天和
- 下一篇: TreeSet的定制排序