Java 集合類是一種特別有用的工具類,大致可分為Set
螃诅、List
啡氢、Queue
、Map
四種體系术裸。
Set代表無序倘是、不可重復(fù)的集合;
List代表有序袭艺、重復(fù)的集合搀崭;
Map代表具有映射關(guān)系的集合;
Queue代表隊列集合猾编。
一瘤睹、集合概述
Java5在java.util.concurrent
包下提供了一些多線程支持的集合類。
集合里只能保存對象答倡。
Java的集合類主要由兩個接口派生:Collection
和Map
轰传。
上圖中
Deque
還有一個實現(xiàn)類ArrayDeque
,只是我沒有找到合適的圖瘪撇。获茬。
最常用的集合類有:HashSet港庄、TreeSet、ArrayDeque恕曲、ArrayList鹏氧、LinkedList、HashMap佩谣、TreeMap
二把还、Collection和Iterator接口
Collection接口里面定義了如下操作集合元素的方法:
- boolean add(Object o)
- boolean addAll(Collection c)
- void clear()
- boolean contains(Object o)
- boolean isEmpty()
- Iterator iterator()
- boolean remove(Object o)
- boolean removeAll(Collection c)
- boolean retainAll(Collection c)
- int size()
- Object[] toArray()
使用lambda表達式遍歷集合
Java8為Iterable接口新增了一個forEach(Consumer action)
默認方法,該方法所需參數(shù)的類型是一個函數(shù)式接口茸俭,Iterable接口是Collection接口的父接口吊履,Collection集合可以使用這個接口。
books.forEach(obj -> System.out.println(obj));
使用Java8增強的Iterator遍歷集合元素
Iterator接口提供了4中方法:
- boolean hasNext()
- Object next()
- void remove()
- void forEachRemaining(Consumer action)
Iterator it = books.iterator();
while(it.hasNext){
String book = (String)it.next();
}
Iterator必須依附于Collection對象瓣履。
使用Lambda表達式遍歷Iterator
it.forEachRemaining(obj->System.out.println(obj));
使用foreach循環(huán)遍歷集合元素
使用Java8新增的predicate操作集合
Java8為Collection集合新增了一個removeIf(Predicate filter)
方法率翅,批量刪除符合filter的元素。
books.removeIf(obj->((String)obj).length()<10);
使用Java8新增的Stream操作集合
Java8新增了Stream
袖迎,IntStream
冕臭,LongStream
,DoubleStream
等流式API燕锥,這些API代表多個支持串行和并行聚集操作的元素辜贵。還有每個Stream提供了Builder
,如Stream.Builder
归形,IntStream.Builder
托慨,開發(fā)者可以通過這些Builder來創(chuàng)建對應(yīng)的流。
獨立使用Stream的步驟:
- 使用Stream的builder類方法創(chuàng)建Builder
- 重復(fù)調(diào)用Builder的add方法添加元素
- 調(diào)用Builder的build方法獲取對應(yīng)的流
- 調(diào)用Stream的聚集操作
Stream提供了大量的方法暇榴,有"中間方法"(生成另外一個流)和"末端方法"(對流的最終操作)厚棵。
常用的中間方法:
- filter(Pridicate predicate)
- mapToXxx(ToXxxFunction Mapper)
- peek(Consumer action)
- distict()
- sorted()
- limit(long maxSize)
常用的末端方法:
- forEache(Consumer action)
- toArray()
- reduce()
- min()
- max()
- count()
- anyMatch(Predicate predicate)
- allMatch(Predicate predicate)
- noneMatch(Predicate predicate)
- findFirst()
- findAny()
Java8為Collection提供了一個stream默認方法。
三蔼紧、Set集合
HashSet類
特點:
- 不能保證順序
- 不能保證同步(多線程)
- 集合元素值可以是null
當向HashSet集合添加一個元素時婆硬,HashSet會調(diào)用該對象的hashCode()方法得到對象的hashCode值,然后根據(jù)該hashCode值決定該對象在HashSet中的存儲位置奸例。
HashSet集合判斷兩個元素相等的標準是兩個對象通過equals()
方法比較相等彬犯,并且兩個對象的hashCode()
方法返回值也想等。
重寫hashCode()方法的基本原則:
- 同一個對象多次調(diào)用應(yīng)該返回相等的值
- 當兩個對象通過
equals()
方法比較返回true時查吊,他們的hashCode()值應(yīng)該相等 - 對象中用于
equals()
比較的實例變量都應(yīng)該用于計算hashCode
重寫hashCode()的一般步驟:
- 把對象內(nèi)每個有意義的實例變量計算出一個int類型的hashCode值谐区。
- 用第一步計算的多個hashCode值組合計算出一個hashCode值返回
hashCode值的計算方式:
變量類型 | 計算方式 |
---|---|
boolean | f?0:1 |
整數(shù)類型 | (int)f |
long | (int)(f^(f>>>32)) |
float | Float.floatToIntBits(f) |
double | d = Double.doubleToLongBits(f);(int)(d^(d>>>32)) |
應(yīng)用類型 | f.hashCode() |
為了避免直接相加的偶然相等,可以通過為各實例變量的hashCode值乘以任意一個質(zhì)數(shù)后再相加逻卖。
LinkedHashSet
也是根據(jù)hashCode插入元素宋列,但是要維護元素的插入順序,性能略低于HashSet评也。
TreeSet
TreeSet是SortedSet的實現(xiàn)類炼杖。有幾個額外方法:
- Comparator comparator()
- Object first()
- Object last()
- Object lower(Object e)
- Object hight(Object e)
- SortedSet subSet(Object fromElement, Object toELement)
- SortedSet headSet(Object toElement)
- SortedSet tailSet(Object toElement)
TreeSet使用紅黑樹的數(shù)據(jù)結(jié)構(gòu)來存儲集合元素戈鲁。支持自然排序和定制排序。
自然排序
調(diào)用集合的compareTo(Object obj)
方法比較元素之間的大小關(guān)系嘹叫,然后按升序排序。
Comparable
接口里定義了一個compareTo(Object obj)
方法诈乒。
如果試圖把一個對象添加到TreSet罩扇,則該對象的類必須實現(xiàn)Comparable
接口。
向TreeSet中插入元素時怕磨,第一個元素不會調(diào)用compareTo()方法
定制排序
創(chuàng)建TreeSet時傳遞給它一個Comparator
對象即可喂饥,該接口是函數(shù)式接口,可以使用lambda表達式創(chuàng)建對象肠鲫。
四员帮、List集合
代表一個元素有序、可重復(fù)的集合导饲,集合中每個元素都有其對應(yīng)的順序索引捞高。
java8改進的List接口和ListIterator接口
List接口的方法:
- void add(int index, Object element)
- boolean addAll(int index, Collection c)
- Object get(int index)
- int indexOf(Object o)
- int lastIndexOf(Object o)
- Object remove(int index)
- Object set(int index, Object element)
- List subList(int fromIndex, int toIndex)
- void replaceAll(UnaryOperator operator)
- void sort(Comparator c)
List判斷兩個對象相等只要通過equals
方法返回true即可。
List除了有Set的iterator()方法之外渣锦,還有l(wèi)istIterator()方法硝岗,該方法返回一個ListIterator對象,ListIterator接口繼承于Iterator接口袋毙。ListIterator相較于Iterator多了如下方法:
- boolean hasPrevious()
- Object previous()
- void add(Object o)
ArrayList和Vector實現(xiàn)類
使用initialCapacity
參數(shù)設(shè)置該數(shù)組的長度型檀。如果需要向集合中添加大量元素,可使用ensureCapacity(int minCapacity)
方法一次性地增加容量听盖,可以減少重分配的次數(shù)胀溺,提高性能。
可以在創(chuàng)建的時候指定initialCapacity
皆看,還可以通過一下兩個方式重新分配Object[]
數(shù)組仓坞,不指定的話默認長度為10:
- void ensureCapacity(int minCapacity)
- void trimToSize()
ArrayList和Vector用法幾乎完全相同,Vector是一個古老的集合悬蔽,里面有重復(fù)的方法扯躺。
通常盡量少用Vector。
Vector是線程安全的蝎困,但效率低录语,ArrayList不是線程安全的,java.util.Collections類可以將ArrayList變成線程安全的禾乘。推薦使用ArrayList澎埠。
Stack是Vector的子類。有以下方法:
- Object peek()
- Object pop()
- void push(Object item)
Stack繼承于Vector始藕,古老的類蒲稳,線程安全氮趋,但是效率低,不建議使用江耀∈P玻可以使用后來的ArrayDeque
類代替。
固定長度的List
Arrays類提供了asList(Object... a)
方法祥国,可以把一個數(shù)組或指定個數(shù)的對象轉(zhuǎn)換成List集合昵观。這個List集合既不是ArrayList實現(xiàn)類的實例,也不是Vector實現(xiàn)類的實例舌稀,而是Arrays的內(nèi)部類ArrayList的實例啊犬。
Arrays.ArrayList是一個固定長度的List集合,只能遍歷壁查,不可增加修改觉至。
五、Queue集合
Queue接口中定義的方法:
- void add(Object e)
- Object element():獲取隊列頭元素睡腿,但不刪除
- boolean offer(Object e):加入元素语御,比add()好
- Object peek():獲取頭元素,如果為空席怪,返回null
- Object poll():獲取頭元素沃暗,并刪除,如果為空何恶,返回null
- Object remove():獲取頭元素孽锥,并刪除
Deque是Queue的子接口,代表雙端隊列细层。有ArrayDeque
和LinkedList
兩個實現(xiàn)類惜辑。
PriorityQueue實現(xiàn)類
內(nèi)部排序。
Deque接口和ArrayDeque實現(xiàn)類
Deque接口方法:
- void addFirst(Object e)
- void addLast(Object e)
- Iterator descendingIterator()
- Object getFirst()
- Object getLast()
- boolean offerFirst(Object e)
- boolean offerLast(Object e)
- Object peekFirst()
- Object peekLast()
- Object pollFirst()
- Object pollLast()
- Object pop()
- void push()
- Object removeFirst()
- Object removeFirstOccurrence(Object o)
- Object removeLast()
- Object removeLastOccurrence(Object o)
LinkedList實現(xiàn)類
LinkedList即可以當成雙端隊列疫赎,也可以當成棧使用盛撑,也可以當成隊列使用。
ArrayList和ArrayDeque內(nèi)部使用數(shù)組實現(xiàn)捧搞,而LinkedList內(nèi)部使用鏈表實現(xiàn)抵卫。
各種線性表的性能分析
整體來說ArrayList比LinkedList性能好。
- 如果需要遍歷List胎撇,對于ArrayList介粘、Vector集合,應(yīng)該使用隨機訪問方法(get())遍歷晚树;對于LinkedList則應(yīng)該采用Iterator遍歷姻采。
- 經(jīng)常插入刪除袱蜡,考慮使用LinkedList
- 多個線程梢卸,可以使用Collections將集合包裝成線程安全的集合。
六赛糟、Java8增強的Map集合
從Java源碼看男摧,Java先實現(xiàn)了Map阁吝,然后通過包裝一個所有value都為null的Map就實現(xiàn)了Set集合声登。
Map的實現(xiàn)子類和子接口中key集的存儲形式和對應(yīng)Set集合中元素的存儲形式完全相同涵紊。
方法:
- void clear()
- boolean containsKey(Object key)
- boolean containsValue(Object value)
- Set entrySet()
返回Map中包含的key-value對所組成的Set集合,每個集合元素都是Map.Entry對象
- Object get(Object key)
- boolean isEmpty()
- Set keySet()
- Object put(Object key, Object value)
- void putAll(Map m)
- Object remove(Object key, Object value)
- int size()
- Collection values()
Map接口中有一個內(nèi)部類Entry蛉签,該類封裝了key-value鍵值對冈涧。Entry包含如下三個方法:
- Object getKey()
- Object getValue()
- Object setValue(V value)
java8新增的方法
- Object compute(Object key, BiFunction remappingFunction)
- Object computeIfAbsent(Object key, Function mappingFunction)
- Object computeIfPresent(Object key, BiFunction remappingFunction)
- void forEach(BiConsumer action)
- Object getOrDefault(Object key, V default Value)
- Object merge(Object key, Object value, BiFunction remappingFunction)
- Object putIfAbsent(Object key, Object value)
- Object replace(Object key, Object value)
- boolean replace(K key, V oldValue, V newValue)
- replaceA(BiFunction Function)
java8改進的Hash Map和Hashtable實現(xiàn)類
hashtable和vector同一時期出現(xiàn)。
區(qū)別:
- Hashtable是線程安全的
- Hashtable不允許null作為key和value
用作key的對象必須實現(xiàn)hashcode()和equals()方法
與HashSet類似正蛙,盡量不要使用可變對象作為HashMap、Hashtable的key营曼。
LinkedHashMap
使用雙向鏈表維護key-value對的次序乒验。
使用Properties讀寫屬性文件
Properties是Hashtable的子類。
- String getProperty(String key)
- String getProperty(String key, String defaultValue)
- String setProperty(String key, String value)
- void load(InputStream inStream)
- void store(OutputStream out, String comments)
SortedMap接口和TreeMap實現(xiàn)類
Map性能分析
HashMap和Hashtable實現(xiàn)機制相同蒂阱,但由于Hashtable是一個古老的锻全、線程安全的集合,HashMap通常比Hashtable快录煤。
TreeMap更慢鳄厌,但是其key-value是有序狀態(tài),無需專門的排序操作妈踊×撕浚可以調(diào)用keySet(),再用toArray()方法廊营,再用Arrays的binarySearch()方法快速查找對象歪泳。
七、操作集合的工具類Collections
排序
- void reverse(List list)
- void shuffle(List list)
- void sort(List list)
- void sort(List list, Comparator c)
- void swap(List list, int i, int j)
- void rotate(List list, int distance)
查找露筒、替換操作
- int binarySearch(List list, Object key)
- Object Max(Collection coll)
- Object Max(Collection coll, Comparator c)
- Object Min(Collection coll)
- Object Min(Collection coll, Comparator c)
- void fill(List list, Object obj)
- int frequency(Collection c, Object o)
- int indexOfSubList(List source, List target)
- int lastIndexOfSubList(List source, List target)
- boolean replaceAll(List list, Object oldVal, Object newVal)
同步控制
synchronizaedXxx()方法呐伞。
設(shè)置不可變集合
- emptyXxx()
- singletonXxx()
- unmodifiableXxx()
九、繁瑣的接口Enumeration
該接口是Iterator
接口的古老版本慎式。
不要使用伶氢,使用Iterator
代替