《瘋狂Java講義》學習筆記(七)Java集合

1、Java集合概述

  • 爲了保存數量不確定的數據,以及保存具有映射關係的數據(關聯數據),Java提供了集合類。Java集合大致可分爲Set、List、Queue和Map四種體系,其中Set代表無序、不可重複的集合;List代表有序、重複的集合;Map代表具有映射關係的集合;Queue代表一種隊列集合實現
  • 集合類和數組不同,數組元素既可以是基本類型的值,也可以是對象;而集合裏只能保存對象,兩者實際保存的是對象的引用變量。
  • Java的集合類主要由兩個接口派生:Collection和Map,兩者是Java集合框架的根接口,這兩個接口又包含了一些子接口或實現類
  • Collection和Map的繼承樹
    四種集合最常用的實現類爲HashSet、TreeSet、ArrayList、ArrayDeque、LinkedList、HashMap和TreeMap等實現類。

2、Collection和Iterator接口

  • Collection接口是List、Set和Queue的父接口,該接口定義的方法三種集合都可用:
boolean add(Object o):往集合裏添加一個元素,添加成功返回true
boolean addAll(Collection c):把集合c裏的所有元素添加到指定集合裏,添加成功返回true
void clear():清除集合裏的所有元素,將集合長度變爲0
boolean contains(Object o):集合裏是否包含指定元素
boolean containsAll(Collection c):集合裏是否包含集合c裏的所有元素
boolean isEmpty():集合是否爲空,當長度爲0時返回true
Iterator iterator():返回一個Iterator對象,用於遍歷集合裏的元素
boolean remove(Object o):刪除集合中的指定元素,當集合包含多個元素o時,只刪除第一個符合的元素並返回true
boolean removeAll(Collection c):從集合中刪除集合c裏包含的所有元素(該集合減去集合c),如果刪除一個或以上的元素返回true
boolean retainAll(Collection c):從集合中刪除集合c裏不包含的元素(交集),操作成功返回true
int size():返回集合裏元素的個數
Object[] toArray():把集合轉換成一個數組
  • Lambda表達式遍歷集合
    Java8爲Iterable(Collection的父接口)接口新增了一個forEach(Consumer action)默認方法
new List<String>().forEach(obj->System.out.println(obj));
  • Java8增強的Iterator遍歷集合元素
boolean hasNext():如果被迭代的集合元素還未被遍歷完,返回true
Object next():返回集合裏的下一個元素
void remove():刪除集合裏上一次next方法返回的元素
void forEachRemaining(Consumer action):可以使用Lambda表達式來遍歷集合元素
List<Student> stuList = new ArrayList<Student>();
stuList.add(new Student("tom",20));
stuList.add(new Student("jack",22));
stuList.forEach(obj->System.out.println(obj.getName()+"\n"+obj.getAge()));
Iterator<Student> iter = stuList.iterator();
iter.forEachRemaining(obj->System.out.println(obj.getName()+"\n"+obj.getAge()));
Iterator必須依附於Collection對象,若有一個Iterator對象,則必然有一個與之關聯的Collection對象
  • Java8新增的Predicate操作集合
removelf(Predicate filter)可以批量刪除符合filter條件的所有元素
stuList.removeIf(obj->obj.getName().equals("tom"));
  • Java8新增的Stream操作集合
stuList.stream().filter(ele->(ele.getAge()>10)).count();
常用APIfilter(Predicate predicate):過濾Stream中所有不符合predicate的元素
distinct():用於排序流中所有重複的元素,調用equals()比較
sorted():排序
forEach(Consumer action):遍歷元素
toArray()
min()
max()
count()
anyMatch(Predicate predicate):判斷流中是否至少包含一個元素符合predicate條件
allMatch():判斷流中是否每個元素都符合predicate條件
noneMatch():判斷流中是否所有元素都不符合predicate條件
findFirst():返回流中的第一個元素
findAny():返回流中的任意一個元素

2、Set集合

  • HashSet類
    該類按Hash算法來存儲集合中的元素,因此具有很好的存取和查找性能
    HashSet不能保證元素的排列順序,順序可能與添加順序不同,也可能發生變化
    HashSet不是同步的,如果多線程同時訪問一個HashSet,則必須通過代碼來保證其同步
    HashSet元素值可以是null
    HashSet判斷兩個元素相等的標準是equal()方法和hashCode()方法同時都相等
    如果兩個對象通過equals()方法比較返回true,則這兩個對象的hashCode值也應該相同
  • LinkedHashSet
    LinkedHashSet是HashSet的子類,也是根據元素的hashCode值來決定元素存儲位置,但它同時使用鏈表維護元素的次序,使得元素看起來是以插入的順序保存,由於需要維護插入順序,因此性能略低於HashSet
  • TreeSet
TreeSet是SortedSet接口的實現類,可以確保集合元素處於排序狀態
常用API:
Comparator comparator():如果TreeSet採用了定製排序,則返回定製排序所使用的Comparator;如果採用了自然排序,返回null
Object first():返回第一個元素
Object last():返回最後一個元素
Object lower(Object e):返回小於指定元素的一個元素
Object higher(object e):返回大於指定元素的一個元素
SortedSet subSet(Object fromElement,Object toElement):返回Set子集,範圍從fromElement(包含)到toElement(不包含)
SortedSet headSet(Object toElement):返回小於toElement元素的Set子集
SortedSet tailSet(Object fromElement):返回大於或等於fromElement元素的Set子集
定製排序:
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getAge() - o2.getAge();
    }
});
TreeSet<Student> ts = new TreeSet<Student>((o1,o2)->{
    return o1.getAge()-o2.getAge();
});
  • EnumSet類
EnumSet是一個專爲枚舉類設計的集合類,所有元素必須都是指定的枚舉類型的枚舉值
EnumSet在內部以位向量的形式存儲,非常搞笑
EnumSet不允許加入null元素
// 輸出[SPRING,SUMMER,FALL,WINTER]
EnumSet<Season> es1 = EnumSet.allOf(Season.class);
// 輸出[]
EnumSet<Season> es2 = EnumSet.noneOf(Season.class);
es2.add(Season.WINTER);
es2.add(Season.SPRING);
// 輸出[SPRING,WINTER]
System.out.println(es2);
// 輸出[SUMMER,WINTER]
EnumSet<Season> es3 = EnumSet.of(Season.SUMMER,Season.WINTER);
// 輸出[SUMMER,FALL,WINTER]
EnumSet<Season> es4 = EnumSet.range(Season.SUMMER,Season.WINTER);
// 輸出[SPRING],es4 + es5 = Season枚舉類的全部枚舉值
EnumSet<Season> es5 = EnumSet.complementOf(es4);
  • Set實現類的性能分析
    EnumSet>HashSet> LinkedHashSet
    三個類都非線程安全,可以通過Collections工具類的synchronizedSortedSet方法來實現線程同步

3、List集合

  • List常用API
void add(int index,Object element):將元素插入到List集合的indexboolean addAll(int index,Collection c):將集合所包含的所有元素插入到List集合的index處
Object get(int index):返回集合index索引處的元素
int indexOf(Object o):返回對象在List集合中第一次出現的位置索引
int lastIndexOf(Object o):返回對象在List集合中最後一次出現的位置索引
Object remove(int index):刪除並返回index索引處的元素
Object set(int index,Object element):將index索引處的元素替換成element對象,返回被替換的舊元素
List subList(int fromIndex,int toIndex):返回從索引fromIndex(包含)到索引toIndex(不包含)處所有集合元素組成子集合
Java8:
void replaceAll(UnaryOperator operator):根據operator指定的計算規則重新設置List集合的所有元素
strList.replaceAll(ele->ele.length()+"")//使用每個字符串的長度作爲新的集合元素
void sort(Comparator c):根據Comparator參數對List集合的元素排序
studentList.sort((o1,o2)->(o1.age-o2.age))
  • 相比Set,List額外提供了一個listIterator()方法,增加了向前迭代
boolean hasPrevious():是否還有上一元素
Object previous():返回上一個元素
void add(Object o):在指定位置插入一個元素,在迭代過程中可以使用該方法向上一次迭代元素的後面添加一個新元素
- ArrayList和Vector實現類
如果一開始就知道集合需要保存多少個元素,可以在創建的時候就指定initialCapacity大小,否則默認長度爲10
void ensureCapacity(int minCapacity):將ArrayList或Vector集合的Object[]數組長度增加大於或等於minCapacity值
void trimToSize():調整ArrayList或Vector集合的Object[]數組長度爲當前元素的個數,可以減少集合對象佔用的存儲空間
ArrayList和Vector在用法上基本相同,但Vector比較古老,一般儘量減少使用
ArrayList是線程不安全的,Vector是線程安全的
Vector提供了一個Stack子類,模擬棧數據,但比較古老,可以用ArrayDeque替代
  • 固定長度的List
可以使用Arrays.asList(Object... a)方法將數組或指定個數的對象轉換成List,但這個List不是ArrayList或Vector實現類的集合,而是Arrays的內部類ArrayList的實例,所以程序只能遍歷訪問集合裏的元素,不可增加、刪除該集合裏的元素

4、Queue集合

Queue用於模擬隊列數據結構,隊列通常是指“先進先出”(FIFO)的容器,通常不允許隨機訪問隊列中的元素
- Queue的常用API

void add(Object e):將指定元素加入到隊列的尾部
Object element():獲取隊列頭部元素,但不刪除該元素
boolean offer(Object e):和add基本相同,當使用有容量限制的隊列時,此方法會更好
Object peek():獲取隊列頭部的元素,但不刪除該元素
Object poll():獲取隊列頭部的元素,並刪除該元素
Object remove():獲取隊列頭部的元素,並刪除該元素
  • PriorityQueue實現類
PriorityQueue保存隊列元素的順序並不是按加入隊列的順序,而是按隊列元素的大小進行重新排序,因此不是標準的隊列實現類
PriorityQueue不允許插入null元素,有兩種排序:
自然排序:隊列中的元素必須實現了Comparable接口
定製排序:創建時傳入一個Comparator對象,匿名內部類實現邏輯
- Deque接口
Deque接口是Queue接口的子接口,它代表一個雙端隊列:
void addFirst(Object e)
void addList(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 e)
Object removeFirst()
Object removeFirstOccurence(Object o)
Object removeLast()
Object removeLastOccurence(Object o)
Deque不僅可以當成雙端隊列使用,而且可以被當成棧來使用,該類包含了pop(出棧)和push(入棧)兩個方法
  • ArrayDeque實現類
ArrayDeque是一個基於數組實現的雙端隊列
模擬棧:
ArrayDeque<Integer> stack = new ArrayDeque<Integer>();
stack.push(1);
stack.push(2);
stack.push(3);
// 3
System.out.println(stack.peek());
// 3
System.out.println(stack.pop());
// [2, 1]
System.out.println(stack);
- LinkedList實現類
LinkedList是List和Deque的實現類,它是一個List集合,可以根據索引來隨機訪問集合中的元素,也可以被當成雙端隊列,還可以當成棧來使用
LinkedList<Integer> linkedList = new LinkedList<Integer>();
// 加入到隊列的尾部
linkedList.offer(1);
// 加入到棧的頂部
linkedList.push(2);
// 加入到隊列的頭部
linkedList.offerFirst(3);
System.out.println(linkedList);
// 訪問棧頂
System.out.println(linkedList.peekFirst());
// 訪問隊列最後一個元素
System.out.println(linkedList.peekLast());
// 將棧頂的元素彈出
System.out.println(linkedList.pop());
// 彈出隊列最後一個元素
System.out.println(linkedList.pollLast());
LinkedList與ArrayList、ArrayDeque的實現機制完全不同,ArrayList和ArrayDeque內部以數組的形式來保存集合中的元素,隨機訪問集合元素時有較好的性能;LinkedList內部以鏈表的形式來保存集合中的
  • 各種線性表性能分析
    如果需要遍歷List集合元素,對於ArrayList、Vector集合,應該使用隨機訪問方法get來遍歷集合元素,性能更好;對於LinkedList集合,則應採用迭代器Iterator來遍歷集合元素
    如果需要經常執行插入、刪除操作來改變包含大量數據的List集合的大小,可以考慮使用LinkedList集合
    如果有多個現場需要同時訪問List集合中的元素,應考慮使用Collections將集合包裝成線程安全的集合

5、Map集合

  • Map用於保存具有映射關係的數據,Map集合裏保存着兩組值,一組值用於保存Map裏的key,另一組值用於保存Map裏的value,key和value都可以是任何引用類型數據
  • key不允許重複,即任何兩個key通過equals方法比較總是返回false
  • key和value之間存在單向一對一關係,Map中的所有key組成一個Set集合,keySet()方法可以獲取,而所有value放在一起看又非常類似一個List,value可以重複,可以根據key來查找
  • Map的常用API:
void clear(Object key):刪除該Map對象中的所有key-value對
boolean containsKey(Object value):查詢Map中是否包含指定的key,如果包含則返回true
boolean containsValue(Object value):查詢Map中是否包含一個或多個value,如果包含則返回true
Set entrySet():返回Map中包含的key-value對所有組成的Set集合,每個集合元素都是Map.Entry(Entry是Map的內部類)對象
Object get(Object key):返回指定key所對象的value;如果不包含則返回null
boolean isEmpty():Map是否爲空,空則返回true
Set keySet():所有key組成的Set集合
Object put(Object key,Object value):添加一個key-value對,如果當前Map中已有一個與該key相等的key-value對,則新的key-value對會覆蓋原來的key-value對
void putAll(Map m):將指定的key-value對複製到本Map中
Object remove(Object key):刪除指定key所對應的key-value對,返回被刪除key所關聯的value,如果該key不存在,返回null
boolean remove(Object key,Object value):java8新增的方法,刪除指定key和value所對應的key-value對,成功返回true
int size():返回該Map裏的key-value對的個數
Collection values():返回該Map裏所有value組成的Collection
  • Map中包括一個內部類Entry,該類封裝了一個key-value對:
Object Entry.getKey()
Object Entry.getValue()
Object Entry.setValue(V value)
  • Java8新增方法
Object compute(Object key,BiFunction remappingFunction):根據原來的key-value計算一個新的value值,只要新value不爲null,就覆蓋原value;如果原value不爲null,新的valuenull,則刪除原key-value對;如果原value、新value同時爲null,那麼該方法不改變key-value對,返回null
Object computelfAbsent(Object key,Function mappingFunction):如果Map本來的valuenull,則根據key計算一個新結果,新結果不爲null則覆蓋value;如果找不到key則新增一組鍵值對
Object computelfPresent(Object key,BiFunction remappingFunction):如果Map本來的valuenull,則根據key、value計算一個新結果,新結果不爲null則覆蓋value;結果爲null則刪除原來鍵值對
void forEach(BiConsumer action)
Object getOrDefault(Object key,V defaultValue):獲取指定key的value,如果該key不存在,則返回defaultValue
Object merge(Object key,Object value,BiFunction remappingFunction):如果原valuenull,則用value覆蓋原value,否則根據原value和新value計算一個新結果覆蓋原value
Object pulfAbsent(Object key,Object value):檢查原value是否爲null,是就覆蓋value
Object replace(Object key,Object value):替換value,如果key不存在,返回null,並不會添加新的鍵值對
boolean replace(K key,V oldValue,V newValue):同上
replaceAll(BiFunction function):根據key-value結算覆蓋value
  • HashMap和Hashtable區別:
Hashtable線程安全,HashMap線程不安全所以性能也高一點
Hashtable不允許使用null作爲key和value;HashMap可以而且可以有無數個valuenull,但key只能有一個是null
爲了成功地在HashMap、Hashtable中存儲和獲取對象,用作key的對象必須實現hashCode()方法和equals方法
  • LinkedHashMap實現類
LinkedHashMap使用雙向鏈表來維護key-value對的次序,迭代順序和插入順序一致,因此避免了對HashMap、Hashtable進行排序,又能避免使用TreeMap所增加成本
  • 使用Properties讀寫屬性文件
Properties類是Hashtable類的子類,可以把Map對象和屬性文件關聯起來,從而可以把Map對象中的key-value對寫入屬性文件中。
String getProperty(String key):獲取Properties中指定屬性名對應的屬性值
String getProperty(String key,String defaultValue):同上,不存在key值時,則返回默認值
Object setProperty(String key,String value):設置屬性值
void load(InputStream inStream):從屬性文件中加載key-value對,把加載到的追加到Properties中
void store(OutputStream out,String comments):將Properties中的key-value對輸出到指定的屬性文件中
  • SortedMap接口和TreeMap實現類
    自然排序:對key進行排序
    定製排序:創建TreeMap時,傳入一個Comparator對象,對所有key進行排序
  • WeakHashMap實現類
    類似HashMap,區別在於引用強弱,HashMap所引用的對象是強引用,即只要在引用就不會被回收;而WeakHashMap則是弱引用,對象被回收後,WeakHashMap會自動刪除對應的key-value
  • IdentityHashMap實現類
    類似HashMap,區別在於對key的比較,IdentityHashMap當且僅當兩個key嚴格相等時,才認爲是相等;而HashMap則只要兩個key通過equals方法比較返回true且hashCode值相等即可
  • EnumMap實現類
    EnumMap是一個與枚舉類一起使用的Map實現,EnumMap中的所有key都必須是單個枚舉類的枚舉值
    創建EnumMap時必須顯式或隱式指定它對應的枚舉類
    EnumMap在內部以數組形式保存,所以這種實現形式非常緊湊和高效
    EnumMap根據key的自然順序來維護key-value對的順序
    EnumMap不允許使用null作爲key,但允許null作爲value
  • 各種Map實現類的性能分析
    EnumMap>Hashtable>HashMap=WeakHashMap>IdentityHashMap>LinkedHashMap>TreeMap

6、操作集合的工具類:Collections

  • 排序
void reverse(List list):反轉指定List集合元素排序順序
void shuffle(List list):隨機排序
void sort(List list):自然順序升序排序
void sort(List list,Comparator c):根據Comparator產生的順序排序
void swap(List list,int i,int j):將指定List集合中的i處元素和j處元素進行交換
void rotate(List list,int distance):當distance爲正數時,將list集合的後distance個元素整體移動到前面;負數則相反
  • 查找、替換操作
int binarySearch(List list,Object key):二分法搜索,前提是保證List中的元素已經處於有序狀態
Object max(Collection coll):根據元素的自然排序,返回最大元素
Object max(Collection coll,Comparator comp):根據指定排序,返回最大元素
Object min(Collection coll)
Object min(Collection coll,Comparator comp)
void fill(List list,Object obj):使用指定obj替換所有元素
int frequency(Collection c,Object o):返回出現次數
int indexOfSubList(List source,List target):返回子List對象在父List對象最後一次出現的位置索引,沒找到則返回-1
boolean replaceAll(List list,Object oldVal,Object newVal):使用一個新值newVal替換List對象的所有舊值oldVal
  • 同步控制
Collections類提供了多個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());
  • 設置不可變集合
emptyXxx():返回一個空的、不可變的集合對象
sigletonXxx():返回一個質保函指定對象的、不可變的集合對象,可以是List也可以是Map
unmodifiableXxx():返回指定集合對象的不可變視圖,ListSet、SortedSet、Map、SortedMap
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章