java核心技术 第11版 集合
java 核心技術第11版 集合
- java集合框架
- 集合接口與實現分離
- Collection接口
- 迭代器
- 泛型實用方法
- API
- 集合框架中的接口
- 鏈表
- API
- 數組列表
- 散列集
- API
- 樹集
- API
- 隊列與雙端隊列
- API
- 優先隊列
- API
- 映射
- 基本映射操作
- API
- 更新映射條目
- 映射視圖
- 弱散列映射
- 鏈接散列集和映射
- 枚舉集與映射
- 表示散列映射
- 視圖與包裝器
- 小集合
- 子范圍
- 不可修改的視圖
- 同步視圖
- 檢查型視圖
- 算法
- 泛型算法
- 排序和混排
- 二分查找
- 簡單算法
- 批操作
- 集合和數組間的轉換
- 遺留的集合
- Hashtable類
- 枚舉
- 屬性映射
- 棧
- 位集
java集合框架
集合接口與實現分離
java集合類庫將接口與實現(implementation)分離
隊列通常有兩種實現方式, 一種是使用循環數組, 一種是使用鏈表。
可以使用接口類型存放集合引用
Queue<Customer> expressLane = new CircularArrayQueue<>(100); expressLane.add(new Customer("Harry"));循環數組容量有限
API文檔中有一組以Abstract開頭的類, 這些類是為類庫實現者設計的, 若想要實現自己的隊列類, 擴展AbstractQueue類比實現Queue接口中所有方法輕松得多
Collection接口
集合類的基本接口是Collection接口
public interface Collection<E> {boolean add(E element);Iterator<E> iterator();... }迭代器
Iterator接口包含四個方法
public interface Iterator<E> {E next();boolean hasNext();void remove();default void forEachRemaining(Consumer<? super E> action); }使用next方法可以諸葛訪問集合中的元素, 若到達集合末尾, 則拋出一個NoSuchElementException。
Collection<String> c = ...; Iterator<String> iter = c.iterator(); while (iter.hasNext()) {String element = iter.next();do something with element }for each循環更加簡練
for (String element: c) {do something with element }也可以調用forEachRemaining方法, 其將對每一個元素調用Iambda表達式
iterator.forEachRemaining(element -> do something with the element);可以將Iterator.next與Inputstream.read看成等效的。
remove會刪除上次調用next時返回的元素
Iterator<String> it = c.iterator(); it.next(); it.remove();若想刪除兩個相鄰的元素
it.remove(); it.next(); it.remove();泛型實用方法
可以編寫任何處理集合類型的實用方法
public static <E> boolean contains(Collection<E> c, Object obj) {for (E element : c){if (element.equals(obj))return true;}return false; }Collection接口聲明了很多有用的方法, 所有實現類都必須提供這些方法
AbstractCollection類保持基礎方法size和iterator仍為抽象方法, 但是為實現者實現了其他例行方法
public abstract class AbstractCollection<E>implements Collection<E> {...public abstract Iterator<E> iterator();public boolean contains(Object obj){for (E element: this) // calls iterator()if(element.equals(obj))return true;return false;}... }Collection接口還有一個很好用的方法
default boolean removeIf(Predicate<? super E> )API
java.util.Collection
- Iterator<E>
iterator()
Returns an iterator over the elements in this collection.
- int
size()
Returns the number of elements in this collection.
- boolean
isEmpty()
Returns true if this collection contains no elements.
- boolean
contains(Object o)
Returns true if this collection contains the specified element.
- boolean
containsAll(Collection<?> c)
Returns true if this collection contains all of the elements in the specified collection.
- boolean
add(E e)
Ensures that this collection contains the specified element (optional operation).
- boolean
addAll(Collection<? extends E> c)
Adds all of the elements in the specified collection to this collection (optional operation).
- boolean
remove(Object o)
Removes a single instance of the specified element from this collection, if it is present (optional operation).
- boolean
removeAll(Collection<?> c)
Removes all of this collection’s elements that are also contained in the specified collection (optional operation).
- default boolean
removeIf(Predicate<? super E> filter)
Removes all of the elements of this collection that satisfy the given predicate.
- void
clear()
Removes all of the elements from this collection (optional operation).
- boolean
retainAll(Collection<?> c)
Retains only the elements in this collection that are contained in the specified collection (optional operation).
- Object[]
toArray()
Returns an array containing all of the elements in this collection.
- <T> T[]
toArray(T[] a)
Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the specified array.
java.util.Iterator< E >
- default void
forEachRemaining(Consumer<? super E> action)
Performs the given action for each remaining element until all elements have been processed or the action throws an exception.
- boolean
hasNext()
Returns true if the iteration has more elements.
- E
next()
Returns the next element in the iteration.
- default void
remove()
Removes from the underlying collection the last element returned by this iterator (optional operation).
集合框架中的接口
集合有兩個基本接口: Collection和Map
映射用put方法插入
V put (K key, V value)讀取使用get方法
V get (K key)List是一個有序集合(ordered collection)。
List定義了多個隨機訪問的方法
void add(int index, E element) void remove (int index) E get (int index) E set (int index, E element)ListIterator接口定義了一個方法用于在迭代器前面增加一個元素
void add(E element)Set等同于Collection接口, 不過其方法定義更加嚴格。
SortedSet和SortedMap接口會提供用于排序的比較器對象, 這兩個接口定義了可以得到集合子集視圖的方法
接口NavigableSet和NabigableMap中包含一些用于搜索和遍歷有序集和映射的方法, TreeSet和TreeMap實現了這些接口
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BeBKOlOU-1625927053107)(E:\學習筆記\java\java核心技術 第11版\image-20210609193454664.png)]
鏈表
java中所有鏈表都是雙向鏈接的
var staff = new LinkedList<String>(); staff.add("Amy"); staff.add("Bob"); staff.add("Carl"); Iterator<String> iter = staff.iterator(); String first = iter.next(); String second = iter.next(); iter.remove(); //remove last visited element集合類庫提供ListIterator子接口, 包含add方法
interface ListIterator<E> extends Iterator<E> {void add(E element);... }還有兩個方法用來反向遍歷鏈表
E previous() boolean hasPrevious()聲明迭代器如下:
ListIterator<String> iter = staff.listIterator(); var staff = new LinkedList<String>(); staff.add("Amy"); staff.add("Bob"); staff.add("Carl"); ListIterator<String> iter = staff.listIterator(); iter.next(); iter.add("Juliet");set方法用一個新元素替換調用next或prevoius方法返回的上一個元素
LIstIterator<String> iter = list.listIterator(); String oldValue = iter.next(); iter.set(newValue);當一個迭代器發現其集合被另一個迭代器修改, 或該集合自身某個方法修改, 會拋出ConcurrentModificationException異常
List<String> list = ...; ListIterator<String> iter1 = list.listIterator(); LIstIterator<String> iter2 = list.listIterator(); iter1.next(); iter2.remove(); iter2.next(); //throws ConcurrentModificationException有一種簡單的方法檢測并發修改:
集合可以跟蹤更改操作的次數, 每個迭代器都會為它負責的更改操作維護一個單獨的更改操作數。每個迭代器方法的開始處檢查它自己的更改操作數是否和集合的更改操作數相等, 若不一致, 拋出一個ConcurrentModificationException
nextIndex和previousIndex方法返回元素的整數索引
package linkedList;import java.util.*;/*** This program demonstrates operations on linked lists.* @author Cay Horstmann*/public class LinkedListTest{public static void main(String[] args) {var a = new LinkedList<String>();a.add("Amy");a.add("Carl");a.add("Erica");var b = new LinkedList<String>();b.add("Bob");b.add("Doug");b.add("Frances");b.add("Gloria");//merge the words from b into aListIterator<String> aIter = a.listIterator();Iterator<String> bIter = b.iterator();while (bIter.hasNext()){if(aIter.hasNext()) aIter.next();aIter.add(bIter.next());}System.out.println(a);//remove every second word from bbIter = b.iterator();while(bIter.hasNext()){bIter.next();if(bIter.hasNext()){bIter.next();bIter.remove();}}System.out.println(b);//bulk operation: remove all words in b from aa.removeAll(b);System.out.println(a);}}API
java.util.List< E >
- ListIterator<E>
listIterator()
Returns a list iterator over the elements in this list (in proper sequence).
- ListIterator<E>
listIterator(int index)
Returns a list iterator over the elements in this list (in proper sequence), starting at the specified position in the list.
- void
add(int index, E element)
Inserts the specified element at the specified position in this list (optional operation).
- boolean
add(E e)
Appends the specified element to the end of this list (optional operation).
- boolean
addAll(int index, Collection<? extends E> c)
Inserts all of the elements in the specified collection into this list at the specified position (optional operation).
- boolean
addAll(Collection<? extends E> c)
Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection’s iterator (optional operation).
- boolean
remove(Object o)
Removes the first occurrence of the specified element from this list, if it is present (optional operation).
- E
get(int index)
Returns the element at the specified position in this list.
- E
set(int index, E element)
Replaces the element at the specified position in this list with the specified element (optional operation).
- int
indexOf(Object o)
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
- int
lastIndexOf(Object o)
Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
java.util.ListIterator< E >
- void
add(E e)
Inserts the specified element into the list (optional operation).
- boolean hasNext()
Returns true if this list iterator has more elements when traversing the list in the forward direction.
- boolean
hasPrevious()
Returns true if this list iterator has more elements when traversing the list in the reverse direction.
- E
next()
Returns the next element in the list and advances the cursor position.
- int
nextIndex()
Returns the index of the element that would be returned by a subsequent call to next().
- E
previous()
Returns the previous element in the list and moves the cursor position backwards.
- int
previousIndex()
Returns the index of the element that would be returned by a subsequent call to previous().
- void
remove()
Removes from the list the last element that was returned by next() or previous() (optional operation).
- void
set(E e)
Replaces the last element returned by next() or previous() with the specified element (optional operation).
java.util.LinkedList< E >
- LinkedList()
Constructs an empty list.
- LinkedList(Collection<? extends E> c)
Constructs a list containing the elements of the specified collection, in the order they are returned by the collection’s iterator.
- void
addFirst(E e)
Inserts the specified element at the beginning of this list.
- void
addLast(E e)
Appends the specified element to the end of this list.
- E
getFirst()
Returns the first element in this list.
- E
getLast()
Returns the last element in this list.
- E
removeFirst()
Removes and returns the first element from this list.
- E
removeLast()
Removes and returns the last element from this list.
數組列表
ArrayList封裝了一個動態再分配的數組
單線程時使用ArrayList, 多線程時使用Vector
散列集
散列表(hash table)用來快速查找對象, 散列表為每個對象計算一個整數稱為散列碼(hash code)
hashCode方法必須與equals方法兼容
通常將桶數設置為預計元素個數的75%-150%, 標準庫默認類值是16
若散列表太滿, 就需要再散列(rehashed), 裝填因子(load factor)默認為0.75.
HashSet類實現了基于散列表的集
package set;import java.util.*;/*** This program uses a set to print all unique words in System.in.* @author Cat Horstmann*/public class SetTest { public static void main(String[] args) {var words = new HashSet<String>();long totalTime = 0;try(var in = new Scanner(System.in)){while(in.hasNext()){String word = in.next();long callTime = System.currentTimeMillis();words.add(word);callTime = System.currentTimeMillis() - callTime;totalTime += callTime;}}Iterator<String> iter = words.iterator();for (int i = 1; i <= 20 && iter.hasNext(); i++) {System.out.println(iter.next());}System.out.println("...");System.out.println(words.size() + " distinct words. " + totalTime + "milliseconds.");}}API
java.util.HashSet< E >
- HashSet()
Constructs a new, empty set; the backing HashMap instance has default initial capacity (16) and load factor (0.75).
- HashSet(int initialCapacity)
Constructs a new, empty set; the backing HashMap instance has the specified initial capacity and default load factor (0.75).
- HashSet(int initialCapacity, float loadFactor)
Constructs a new, empty set; the backing HashMap instance has the specified initial capacity and the specified load factor.
- HashSet(Collection<? extends E> c)
Constructs a new set containing the elements in the specified collection.
java.lang.Object
- int
hashCode()
Returns a hash code value for the object.
樹集
樹集與散列集十分類似, 不過樹集是一個有序集合(sorted collection), 當前實現使用的是紅黑樹(red-black tree)
treeSet/TreeSetTest.java
package treeSet; import java.util.*;/*** This program sorts a set of Item objects by comparing their descriptions.* @author Cay Horstmann*/public class TreeSetTest {public static void main(String[] args) {var parts = new TreeSet<Item>();parts.add(new Item("Toaster", 1234));parts.add(new Item("Widget", 4562));parts.add(new Item("Modem", 9912));System.out.println(parts);var sortByDescription = new TreeSet<Item>(Comparator.comparing(Item::getDescription));sortByDescription.addAll(parts);System.out.println(sortByDescription);} }treeSet/Item.java
package treeSet;import java.util.*;/*** An item with a description and a part number.*/public class Item implements Comparable<Item> {private String description;private int partNumber;/*** Constructs an item.* @param aDescription the item's description* @param aPartNumber the item's part number*/public Item(String aDescription, int aPartNumber){description = aDescription;partNumber = aPartNumber;}/*** Gets the description of this item.* @return the description*/public String getDescription() {return description;}@Overridepublic String toString() {return "[description=" + description + ", partNumber=" + partNumber + "]";}@Overridepublic boolean equals(Object otherObject) {if(this == otherObject) return true;if(otherObject == null) return false;if(getClass() != otherObject.getClass()) return false;var other = (Item)otherObject;return Objects.equals(description, other.description) && partNumber == other.partNumber;}@Overridepublic int hashCode() {return Objects.hash(description, partNumber);}@Overridepublic int compareTo(Item other) {int diff = Integer.compare(partNumber, other.partNumber);return diff!= 0 ? diff : description.compareTo(other.description);} }API
java.util.TreeSet< E >
- TreeSet()
Constructs a new, empty tree set, sorted according to the natural ordering of its elements.
- TreeSet(Collection<? extends E> c)
Constructs a new tree set containing the elements in the specified collection, sorted according to the natural ordering of its elements.
- TreeSet(Comparator<? super E> comparator)
Constructs a new, empty tree set, sorted according to the specified comparator.
- TreeSet(SortedSet<E> s)
Constructs a new tree set containing the same elements and using the same ordering as the specified sorted set.
java.util.SortedSet< E >
- Comparator<? super E>
comparator()
Returns the comparator used to order the elements in this set, or null if this set uses the natural ordering of its elements.
- E
first()
Returns the first (lowest) element currently in this set.
- E
last()
Returns the last (highest) element currently in this set.
java.util.NavigableSet < E >
- E
higher(E e)
Returns the least element in this set strictly greater than the given element, or null if there is no such element.
- E
lower(E e)
Returns the greatest element in this set strictly less than the given element, or null if there is no such element.
- E
ceiling(E e)
Returns the least element in this set greater than or equal to the given element, or null if there is no such element.
- E
floor(E e)
Returns the greatest element in this set less than or equal to the given element, or null if there is no such element.
- E
pollFirst()
Retrieves and removes the first (lowest) element, or returns null if this set is empty.
- E
pollLast()
Retrieves and removes the last (highest) element, or returns null if this set is empty.
- Iterator<E>
descendingIterator()
Returns an iterator over the elements in this set, in descending order.
隊列與雙端隊列
雙端隊列(deque)允許在頭部和尾部都高效地添加元素, ArrayDequeue和LinkedList都實現了Deque, 使用這兩個類可以實現雙端隊列
API
java.util.Queue< E >
- boolean
add(E e)
Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions, returning true upon success and throwing an IllegalStateException if no space is currently available.
- boolean
offer(E e)
Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions.
- E
remove()
Retrieves and removes the head of this queue.
- E
poll()
Retrieves and removes the head of this queue, or returns null if this queue is empty.
- E
element()
Retrieves, but does not remove, the head of this queue.
- E
peek()
Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
java.util.Deque< E >
- void
addFirst(E e)
Inserts the specified element at the front of this deque if it is possible to do so immediately without violating capacity restrictions, throwing an IllegalStateException if no space is currently available.
- void
addLast(E e)
Inserts the specified element at the end of this deque if it is possible to do so immediately without violating capacity restrictions, throwing an IllegalStateException if no space is currently available.
- boolean
offerFirst(E e)
Inserts the specified element at the front of this deque unless it would violate capacity restrictions.
- boolean
offerLast(E e)
Inserts the specified element at the end of this deque unless it would violate capacity restrictions.
- E
removeFirst()
Retrieves and removes the first element of this deque.
- E
removeLast()
Retrieves and removes the last element of this deque.
- E
pollFirst()
Retrieves and removes the first element of this deque, or returns null if this deque is empty.
- E
pollLast()
Retrieves and removes the last element of this deque, or returns null if this deque is empty.
- E
getFirst()
Retrieves, but does not remove, the first element of this deque.
- E
getLast()
Retrieves, but does not remove, the last element of this deque.
- E
peekFirst()
Retrieves, but does not remove, the first element of this deque, or returns null if this deque is empty.
- E
peekLast()
Retrieves, but does not remove, the last element of this deque, or returns null if this deque is empty.
java.util.ArrayDeque< E >
- ArrayDeque()
Constructs an empty array deque with an initial capacity sufficient to hold 16 elements.
- ArrayDeque(int numElements)
Constructs an empty array deque with an initial capacity sufficient to hold the specified number of elements.
優先隊列
優先隊列( priority queue)中的元素可以按照任意的順序插入, 但對按照有序的順序進行檢索。
因為優先隊列使用了堆(heap)的數據結構, 堆是一個可以自組織的二叉樹, 若母節點的值恒小于子節點, 稱為最小堆, 反之稱為最大堆
package priorityQueue;import java.util.*;import java.time.*;/*** This program demonstrates the use of a priority queue.* @author Cay Horstmann*/public class PriorityQueueTest {public static void main(String[] args) {var pq = new PriorityQueue<LocalDate>();pq.add(LocalDate.of(1906, 12, 9)); //G.Hopperpq.add(LocalDate.of(1815, 12, 10));pq.add(LocalDate.of(1903, 12, 3));pq.add(LocalDate.of(1910, 6, 22));System.out.println("Iterating over elements...");for (LocalDate date : pq) System.out.println(date);System.out.println("Removing elements...");while(!pq.isEmpty())System.out.println(pq.remove());} }API
java.util.PriorityQueue
- PriorityQueue()
構造一個空的優先隊列(容量默認11)
PriorityQueue(int initialCapacity)構造一個具有指定容量的優先隊列
- PriorityQueue(int initialCapacity, Comparator<? super E> c)
構造一個使用指定比較器的優先隊列
映射
基本映射操作
如果不需要按照有序的順序訪問鍵, 散列映射相對更快
size方法返回映射中的元素數, 可以用lambda表達式對映射進行迭代處理
score.forEach(k, v) ->System.out.println("key=" + K + ", value=" + v); package map; import java.util.*;/*** This program demonstrates the use of a map with key type String and value type Employee.* @author Cay Horstmann*/public class MapTest {public static void main(String[] args){var staff = new HashMap<String, Employee>();staff.put("144-25-5464", new Employee("Amy Lee"));staff.put("567-24-2546", new Employee("Harry Hacker"));staff.put("157-62-7935", new Employee("Gary Cooper"));staff.put("456-62-5527", new Employee("Francesca Cruz"));//print all entriesSystem.out.println(staff);//remove an entrystaff.remove("567-24-2546");//replace an entrystaff.put("456-62-5527", new Employee("Francesca Miller"));//look up a valueSystem.out.println(staff.get("157-62-7935"));// iterate through all entriesstaff.forEach((k, v) ->System.out.println("key=" + k + ", value=" + v));}}API
java.util.Map<K, V>
- V
get(Object key)
Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
- default V
getOrDefault(Object key, V defaultValue)
Returns the value to which the specified key is mapped, or defaultValue if this map contains no mapping for the key.
- V
put(K key, V value)
Associates the specified value with the specified key in this map (optional operation).
- void
putAll(Map<? extends K,? extends V> m)
Copies all of the mappings from the specified map to this map (optional operation).
- boolean
containsKey(Object key)
Returns true if this map contains a mapping for the specified key.
- boolean
containsValue(Object value)
Returns true if this map maps one or more keys to the specified value.
- default void
forEach(BiConsumer<? super K,? super V> action)
Performs the given action for each entry in this map until all entries have been processed or the action throws an exception.
java.util.HashMap< K, V >
Constructs an empty HashMap with the default initial capacity (16) and the default load factor (0.75).
Constructs an empty HashMap with the specified initial capacity and the default load factor (0.75).
Constructs an empty HashMap with the specified initial capacity and load factor.
java.util.TreeMap< K, V >
- TreeMap()
Constructs a new, empty tree map, using the natural ordering of its keys.
TreeMap(Comparator<? super K> comparator)Constructs a new, empty tree map, ordered according to the given comparator.
TreeMap(Map<? extends K,? extends V> m)Constructs a new tree map containing the same mappings as the given map, ordered according to the natural ordering of its keys.
TreeMap(SortedMap<K,? extends V> m)Constructs a new tree map containing the same mappings and using the same ordering as the specified sorted map.
java.util. SortedMap< K, V>
- Comparator<? super K>
comparator()
Returns the comparator used to order the keys in this map, or null if this map uses the natural ordering of its keys.
- K
firstKey()
Returns the first (lowest) key currently in this map.
- K
lastKey()
Returns the last (highest) key currently in this map.
更新映射條目
更新映射有如下方式:
counts.put(word, counts.get(word) + 1);但是第一次見到word時會有問題
counts.put(word, counts.getOrDefaule(word, 0) + 1);另一種方法是使用putIfAbsent
counts.putIfAbsent(word, 0); counts.put(word, counts.get(word) + 1);merge方法更為方便
counts.merge(word, 1, Integer::sum);映射視圖
可以得到映射的視圖(view)
Set< K > KeySet(); Collection< V > values(); Set< Map.Entry< K, V > > entrySet();分別返回鍵集合, 值集合, 鍵值對集合
Set接口擴展了Collection接口
Set< String > keys = map.keySet(); for (String key: keys) {do something with key }若想同時查看鍵和值
for (Map.Entry< String, Employee> entry : staff.entrySet()) {String k = entry.getKey();Empolyee v = entry.getValue();do something with key, value } for (var entry: map.entrySet()) {do something with entry.getKey(), entry.getValue() }現在只需要使用forEach方法
map.forEach((k, v) -> {do something with k, v });鍵集視圖可以調用迭代器的remove方法, 但不能進行添加, 映射條目集視圖同樣
弱散列映射
當對鍵的最后一個引用都沒有時(此時對鍵的唯一引用來自于散列表映射條目時), WeakHashMap類可以與垃圾回收器一起刪除鍵值對
WeakHashMap類使用弱引用(weak references)保存鍵
如果某個對象沒有被他人再引用時, 垃圾回收器會將其回收
如果某個對象只由WeakReference引用時, 垃圾回收也會將其回收, 其將會將該對象的一個弱引用加入隊列, WeakHashMap檢查隊列, 刪除相關聯的映射條目
鏈接散列集和映射
LinkedHashMap和LinkedHashSet 由雙向鏈表實現, 會記住插入元素項的順序(TreeSet使用的是大小順序, HashSet使用隨機順序)。
連接散列映射使用訪問順序來迭代處理映射條目
每次使用get或put時會將項放到鏈表的尾部
構造散列映射使用
LinkedHashMap< K, V > (initialCapacity, loadFactor, true)作為一般規則,默認負載因子(0.75)在時間和空間成本上提供了很好的折衷。較高的值會降低空間開銷,但提高查找成本(體現在大多數的HashMap類的操作,包括get和put)。設置初始大小時,應該考慮預計的entry數在map及其負載系數,并且盡量減少rehash操作的次數。如果初始容量大于最大條目數除以負載因子,rehash操作將不會發生。
當在表中找不到元素項且表相當滿時, 可以得到表的一個迭代器, 刪除其枚舉的前幾個項, 這些項會是近期最少使用的幾個元素。
可以通過構造子類, 覆蓋方法來實現自動化
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) var cache = new LinkedHashMap<K, V>(128, 0.75F,true) {protected boolean removeEldestEntry(Map.entry<K, V> eldest){return size() > 100;} }當方法返回true時, 添加一個新映射條目將會刪除eldest項
枚舉集與映射
EnumSet是枚舉類型元素集的高效實現, EnumSet內部使用位序列實現, 若對應的值在集中, 相應的位被設置為1
EnumSet使用靜態工廠方法構造
enum Weekday {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY};EnumSet<Weekday> always = EnumSet.allof(Weekday.class);EnumSet<Weekday> never = EnumSet.noneOf(Weekday.class);EnumSet<Weekday> workday = EnumSet.range(Weekday.MONDAY, Weekday.FRIDAY);EnumSet<Weekday> mwf = EnumSet.of(Weekday.MONDAY, Weekday.WEDNESDAY, Weekday.FRIDAY);可以使用set’常用接口來修改EnumSet
EnumMap是一個鍵類型位枚舉類型的映射, 直接且高效地實現為一個值數組。需要在構造器中指定鍵類型
var personInCharge = new EnumMap<Weekday, Employee>(Weekday.class);表示散列映射
IdentityHashMap類中, 鍵的散列值使用System.identityHashCode計算, 這是Object.hashCode的計算方法
IdentityHashMap類使用==進行比較, 而不是equals
視圖與包裝器
keySet方法返回一個 實現了Set接口的類對象, 由這個類的方法操縱原映射
小集合
List<String> names = List.of("Peter", "Paul", "Mary"); Set<Integer> numbers = Set.of(2, 3, 5);對于映射
Map<String, Integer> scores = Map.of("Peter", 2, "Paul", 3, "Mary", 5);元素, 鍵或值不能為null
對于Map接口, 無法提供參數可變的of方法版本, 因為參數類型會在鍵和值類型之間交替
不過其ofEntries靜態方法可以實現
import static java.util.Map.*; ... Map<String, Integer> scores = ofentries(entry("Peter", 2), entry("Paul", 3),entry("Mary", 5));of或ofEntries方法生成的集合對象無法更改
var names = new ArrayList<>(List.of("Peter", "Paul", "Mary"));方法調用
Collections.nCopies(n, anObject)會返回一個實現了List接口的不可變對象
List<String> settings = Collections.nCopies(100, "DEFAULT");子范圍
若想取出第10到第19個元素
List<Employee> group2 = staff.subList(10, 20);該方法與String類的substring方法參數情況相同。
對子范圍操作會自動反映到整個列表。
對于有序集和映射, 可以適應排序順序建立子范圍
SortedSet<E> subSet(E from, E to); SortedSet<E> headSet(E to); SortedSet<E> tailSet(E from); SortedMap<K, V> subMap(K from, K to); SortedMap<K, V> headMap(K to); SortedMap<K, v> tailMap(K from);java6引入的NavigableSet接口允許更多地控制子范圍操作, 包括指定是否包括邊界
NavigableSet<E> subSet(E from, boolean fromInclusive,E to, boolean toInclusive); NavigableSet<E> headSet(E to, boolean toInclusive); NavigableSet<E> tailSet(E from, boolean fromInclusive);不可修改的視圖
Collections類中由生成不可改變視圖的幾個方法(unmodifiable view)。
使用如下8個方法來獲得不可修改視圖
Collections.unmodifiableCollection; Collections.unmodifiableList; Collections.unmodifiableSet; Collections.unmodifiableSortedSet; Collections.unmodifiableNavigableSet; Collections.unmodifiableMap; Collections.unmodifiableSortedMap; Collections.unmodifiableNavigableMap; var staff = new LinkedList<String>(); ... lookAt(Collections.unmodifiableList(staff));同步視圖
視圖機制確保了常規集合是線程安全的, 而沒有實現線程安全的集合類
Collections類的靜態synchronizedMap方法可以將任何一個映射轉換為有同步訪問方法的Map
var map = Collections.synchronizedMap(new HashMap< String, Emloyee >());檢查型視圖
var strings = new ArrayList<String>(); ArrayList rawList = strings; //warning only, not an error,//for conpatibility with legacy code rawList.add(new Date()); //now strings contains a Date object!只有當調用get時, 會出現報錯。
檢查型視圖可以檢測該類問題
List<String> safeStrings = Collections.checkedList(strings, String.class);算法
泛型算法
找出數組中最大元素:
if(a.length == 0) throw new NoSuchElementException(); T largest = a[0]; for (int i = 1; i < a.length; i++)if(largest.compareTo(a[i]) < 0)largest = a[i];數組列表最大元素:
if(v.size() == 0) throw new NoSuchElementException(); T largest = v.get(0); for(int i = 1; i < v.size(); i++)if(largest.compareTo(v.get(i)) < 0)largest = v.get(i);鏈表:
if (l.isEmpty()) throw new NoSuchElementException(); Iterator<T> iter = l.iterator(); T.largest = iter.next(); while(iter.hasNext()) {T next = iter.next();if(largest.compareTo(next) < 0)largest = next; }泛型算法:
public static <T extends Comparable> T max(Collection<T> c){if(c.isEmpty()) throw new NoSuchElementException();Iterator<T> iter = c.iterator();T largest = iter.next();while(iter.hasNext()){T next = iter.next();if(largest.compareTo(next) < 0)largest = next;}return largest;}排序和混排
Collections類中sort方法可以對實現了List接口的集合進行排序
var staff = new LinkedList<String>(); ... Collections.sort(staff);該調用默認使用默認比較器
使用List接口的sort方法并傳入一個Comparator對象,可采用其他原則排序
staff.sort(Comparator.comparingDouble(Employee::getSalary));降序排序:
staff.sort(Comparator.reverseOrder()) staff.sort(Comparator.comparingDouble(Employee::getSalary).reversed())Collections類中shuffle算法實現隨機混排。
package shuffle;import java.util.*;/*** This program demonstrates the random shuffle and sort algorithms.* @author Cay Horstmann*/ public class ShuffleTest {public static void main(String[] args) {var numbers = new ArrayList<Integer>();for (int i = 1; i <= 49 ; i++){numbers.add(i);}Collections.shuffle(numbers);List<Integer> winningCombination = numbers.subList(0, 6);System.out.println(numbers);Collections.sort(winningCombination);System.out.println(winningCombination);System.out.println(numbers);} }二分查找
Collections類實現了binarySearch方法
前提: 集合必須有序
i = Collections.binarySearch(c, element); i = Collections.binarySearch(c, element, comparator);簡單算法
Collections.replaceAll(words, "C++", "Java");等于以下方法
for (int i = 0; i < words.size(); i++)if(words.get(i).equals("C++")) words.set(i, "java");Collection.removeIf和List.replaceAll需要提供一個lambda表達式來測試或轉換元素
words.removeIf(w -> w.length() <= 3); words.replaceAll(String.toLowerCase);批操作
從coll1中刪除coll2的元素
coll1.removeAll(coll2);找出交集:
var result = new HashSet<String>(firstSet); result.retainAll(secondSet); staff.subList(0, 10),clear();集合和數組間的轉換
String [] values = ...; var staff = new HashSet<>(List.of(values));集合到數組有些困難
Object[] values = staff.toArray(); //toArray方法創建Object[]數組, 不能強制類型轉換 String[] values = staff.toArray(new String[0]); //返回的數組創建相同數據類型 staff.toArray(new String[staff.size()]); //在這種情況下不會創建新數組遺留的集合
Hashtable類
Hashtable和HashMap一樣
枚舉
遺留的集合使用Enumeration接口遍歷元素序列, 實現的兩個方法為hasMoreElements 和nextElement
可以使用Collections.list將元素收集到一個ArrayList中
ArrayList<String> loggerNames = Collections.list(LogManager.getLoggerNames());靜態方法Collections.enumeration產生枚舉對象
List<InputStream> streams = ...; var in = new SequenceInputStream(Collections.enumeration(stream));屬性映射
屬性映射(property map)是一個特殊類型的映射結構
實現類名為Properties
對于指定程序的配置選項很有用
var settings = new Properties(); setting.setProperty("width", "600.0"); setting.setProperty("filename", "home/cay/books/cj11/code/v1ch11/raven.html");使用store方法保存到文件
var out = new FileOutputStream("program.properies"); setting.store(out, "Program Properties");加載使用如下調用
var in = new FileInputStream("program.properties"); setting.load(in);System.getProperties方法生成Properties對象描述信息
getProperty方法1生成描述的字符串
String userDir = System.getProperty("user.home");如下調用當鍵不存在時自動設置為相應的字符串
String filename = setting.getProperty("filename", "");可以將所有默認值放在一個二級屬性映射中, 并在主屬性映射構造器中提供該二級映射。
var defaultSettings = new Properties(); defaultSettings.setProperty("width", "600"); defaultSettings.setProperty("height", "400"); dafaultSettings.setProperty("filename", ""); ... var settings = new Properties(dafaultSettings);棧
Stack類有push方法和pop方法與peek方法
位集
BitSet類用于存儲一個位序列
位集將位包裝在字節中, 使用位集比使用Boolean對象的ArrayList更高效
package sieve;import java.util.BitSet;/*** This program runs the Sieve of Erathostenes benchmark. It computes all primes* up to 2,000,000* @author Cay Horstmann*/ public class Sieve {public static void main(String[] args) {int n = 2000000;long start = System.currentTimeMillis();var bitSet = new BitSet(n + 1);int count = 0;int i;for (i = 2; i <= n; i++){bitSet.set(i);}i = 2;while(i * i <= n){if(bitSet.get(i)){count++;int k = 2 * i;while(k <= n){bitSet.clear(k);k += i;}}i++;}while(i <= n){if(bitSet.get(i)) count++;i++;}long end = System.currentTimeMillis() ;System.out.println(count + "primes");System.out.println((end - start) + "milliseconds");} } /***@author Cay Horstmann*/ #include <bitset> #include <iostream> #include <ctime>using namespace std;int main() {const int N = 2000000;clock_t cstart = clock();bitset<N + 1> b;int count = 0;int i;for (i = 2; i <= N; i++)b.set(i);i = 2;while (i * i <= N){if (b.test(i)){count++;int k = 2 * i;while (k <= N){b.reset(k);k += i;}}i++;}while (i <= N){if (b.test(i))count++;i++;}clock_t cend = clock();double millis = 1000.0 * (cend - cstart) / CLOCKS_PER_SEC;cout << count << "primes\n" << millis << "milliseconds\n";return 0; }(“width”, “600”);
defaultSettings.setProperty(“height”, “400”);
dafaultSettings.setProperty(“filename”, “”);
…
var settings = new Properties(dafaultSettings);
總結
以上是生活随笔為你收集整理的java核心技术 第11版 集合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: R语言笔记完整版
- 下一篇: JavaScript 封装对象与强制类型