從0開始復(fù)習(xí)java(5)--Collection

Java 集合類是一種特別有用的工具類,大致可分為Set、List、QueueMap四種體系。

Set代表無序、不可重復(fù)的集合;
List代表有序、重復(fù)的集合;
Map代表具有映射關(guān)系的集合;
Queue代表隊(duì)列集合。

一、集合概述

Java5在java.util.concurrent包下提供了一些多線程支持的集合類。

集合里只能保存對象。

Java的集合類主要由兩個接口派生:CollectionMap。

Collection體系的繼承樹
Collection體系的繼承樹

上圖中Deque還有一個實(shí)現(xiàn)類ArrayDeque,只是我沒有找到合適的圖。。

Map體系的繼承樹
Map體系的繼承樹

最常用的集合類有: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表達(dá)式遍歷集合

Java8為Iterable接口新增了一個forEach(Consumer action)默認(rèn)方法,該方法所需參數(shù)的類型是一個函數(shù)式接口,Iterable接口是Collection接口的父接口,Collection集合可以使用這個接口。

books.forEach(obj -> System.out.println(obj));

使用Java8增強(qiáng)的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表達(dá)式遍歷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新增了StreamIntStream,LongStreamDoubleStream等流式API,這些API代表多個支持串行和并行聚集操作的元素。還有每個Stream提供了Builder,如Stream.Builder,IntStream.Builder,開發(fā)者可以通過這些Builder來創(chuàng)建對應(yīng)的流。

獨(dú)立使用Stream的步驟:

  1. 使用Stream的builder類方法創(chuàng)建Builder
  2. 重復(fù)調(diào)用Builder的add方法添加元素
  3. 調(diào)用Builder的build方法獲取對應(yīng)的流
  4. 調(diào)用Stream的聚集操作

Stream提供了大量的方法,有"中間方法"(生成另外一個流)和"末端方法"(對流的最終操作)。

常用的中間方法:

  1. filter(Pridicate predicate)
  2. mapToXxx(ToXxxFunction Mapper)
  3. peek(Consumer action)
  4. distict()
  5. sorted()
  6. limit(long maxSize)

常用的末端方法:

  1. forEache(Consumer action)
  2. toArray()
  3. reduce()
  4. min()
  5. max()
  6. count()
  7. anyMatch(Predicate predicate)
  8. allMatch(Predicate predicate)
  9. noneMatch(Predicate predicate)
  10. findFirst()
  11. findAny()

Java8為Collection提供了一個stream默認(rèn)方法。

三、Set集合

HashSet類

特點(diǎn):

  • 不能保證順序
  • 不能保證同步(多線程)
  • 集合元素值可以是null

當(dāng)向HashSet集合添加一個元素時,HashSet會調(diào)用該對象的hashCode()方法得到對象的hashCode值,然后根據(jù)該hashCode值決定該對象在HashSet中的存儲位置。

HashSet集合判斷兩個元素相等的標(biāo)準(zhǔn)是兩個對象通過equals()方法比較相等,并且兩個對象的hashCode()方法返回值也想等。

重寫hashCode()方法的基本原則:

  • 同一個對象多次調(diào)用應(yīng)該返回相等的值
  • 當(dāng)兩個對象通過equals()方法比較返回true時,他們的hashCode()值應(yīng)該相等
  • 對象中用于equals()比較的實(shí)例變量都應(yīng)該用于計(jì)算hashCode

重寫hashCode()的一般步驟:

  1. 把對象內(nèi)每個有意義的實(shí)例變量計(jì)算出一個int類型的hashCode值。
  2. 用第一步計(jì)算的多個hashCode值組合計(jì)算出一個hashCode值返回

hashCode值的計(jì)算方式:

變量類型 計(jì)算方式
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()

為了避免直接相加的偶然相等,可以通過為各實(shí)例變量的hashCode值乘以任意一個質(zhì)數(shù)后再相加。

LinkedHashSet

也是根據(jù)hashCode插入元素,但是要維護(hù)元素的插入順序,性能略低于HashSet。

TreeSet

TreeSet是SortedSet的實(shí)現(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,則該對象的類必須實(shí)現(xiàn)Comparable接口。

向TreeSet中插入元素時,第一個元素不會調(diào)用compareTo()方法

定制排序

創(chuàng)建TreeSet時傳遞給它一個Comparator對象即可,該接口是函數(shù)式接口,可以使用lambda表達(dá)式創(chuàng)建對象。

四、List集合

代表一個元素有序、可重復(fù)的集合,集合中每個元素都有其對應(yīng)的順序索引。

java8改進(jìn)的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實(shí)現(xiàn)類

使用initialCapacity參數(shù)設(shè)置該數(shù)組的長度。如果需要向集合中添加大量元素,可使用ensureCapacity(int minCapacity)方法一次性地增加容量,可以減少重分配的次數(shù),提高性能。

可以在創(chuàng)建的時候指定initialCapacity,還可以通過一下兩個方式重新分配Object[]數(shù)組,不指定的話默認(rèn)長度為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,古老的類,線程安全,但是效率低,不建議使用??梢允褂煤髞淼?code>ArrayDeque類代替。

固定長度的List

Arrays類提供了asList(Object... a)方法,可以把一個數(shù)組或指定個數(shù)的對象轉(zhuǎn)換成List集合。這個List集合既不是ArrayList實(shí)現(xiàn)類的實(shí)例,也不是Vector實(shí)現(xiàn)類的實(shí)例,而是Arrays的內(nèi)部類ArrayList的實(shí)例。

Arrays.ArrayList是一個固定長度的List集合,只能遍歷,不可增加修改。

五、Queue集合

Queue接口中定義的方法:

  • void add(Object e)
  • Object element():獲取隊(duì)列頭元素,但不刪除
  • boolean offer(Object e):加入元素,比add()好
  • Object peek():獲取頭元素,如果為空,返回null
  • Object poll():獲取頭元素,并刪除,如果為空,返回null
  • Object remove():獲取頭元素,并刪除

Deque是Queue的子接口,代表雙端隊(duì)列。有ArrayDequeLinkedList兩個實(shí)現(xiàn)類。

PriorityQueue實(shí)現(xiàn)類

內(nèi)部排序。

Deque接口和ArrayDeque實(shí)現(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實(shí)現(xiàn)類

LinkedList即可以當(dāng)成雙端隊(duì)列,也可以當(dāng)成棧使用,也可以當(dāng)成隊(duì)列使用。

ArrayList和ArrayDeque內(nèi)部使用數(shù)組實(shí)現(xiàn),而LinkedList內(nèi)部使用鏈表實(shí)現(xiàn)。

各種線性表的性能分析

整體來說ArrayList比LinkedList性能好。

  1. 如果需要遍歷List,對于ArrayList、Vector集合,應(yīng)該使用隨機(jī)訪問方法(get())遍歷;對于LinkedList則應(yīng)該采用Iterator遍歷。
  2. 經(jīng)常插入刪除,考慮使用LinkedList
  3. 多個線程,可以使用Collections將集合包裝成線程安全的集合。

六、Java8增強(qiáng)的Map集合

從Java源碼看,Java先實(shí)現(xiàn)了Map,然后通過包裝一個所有value都為null的Map就實(shí)現(xiàn)了Set集合。

Map的實(shí)現(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改進(jìn)的Hash Map和Hashtable實(shí)現(xiàn)類

hashtable和vector同一時期出現(xiàn)。

區(qū)別:

  1. Hashtable是線程安全的
  2. Hashtable不允許null作為key和value

用作key的對象必須實(shí)現(xiàn)hashcode()和equals()方法

與HashSet類似,盡量不要使用可變對象作為HashMap、Hashtable的key。

LinkedHashMap

使用雙向鏈表維護(hù)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實(shí)現(xiàn)類

Map性能分析

HashMap和Hashtable實(shí)現(xiàn)機(jī)制相同,但由于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代替

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,706評論 18 399
  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,454評論 0 16
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX閱讀 963評論 0 1
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,648評論 0 3
  • 一座寺院,依山傍塬,經(jīng)風(fēng)見雨,聳立數(shù)百年,乍見之,依然恢弘彌新。 八寶如意塔是釋迦摩尼功德的展示場,大金瓦殿、大經(jīng)...
    秋水長天白銀閱讀 370評論 0 3

友情鏈接更多精彩內(nèi)容