第十七章 容器深入研究
17.1 完整的容器分类法
上图虚线框表示接口,长虚线框表示abstract类。空心箭头表示一个特定的类实现了一个接口。实心箭头某个类可以生成箭头所指类的对象。
17.2 填充容器
Collections.nCopies
List<StringAddress> list= new ArrayList<StringAddress>(
Collections.nCopies(4, new StringAddress("Hello")));
Collections.fill
list = Collections.fill(list, new new StringAddress("Hello"));
17.2.1 一种Generator解决方法
17.2.2 Map生成器
17.2.3 使用Abstract类
17.3 Collections的功能方法
- 添加
方法 | 解释 |
---|---|
boolean add(T) | 添加一个元素T,成功返回true |
boolean addAll(Collection<? extends T>) | 添加参数中的所有参数 |
- 查询类
方法 | 解释 |
---|---|
int size() | 添加一个元素T,成功返回true 返回容器元素数目 |
boolean isEmpty() | 查询容器是否为空 |
boolean contains(T) | 查询容器是否包含某元素 |
boolean containsAll(Collection<? extends T>) | 查询是否包含容器内所有元素 |
- 删除类
方法 | 解释 |
---|---|
boolean remove(T) | 删除一个元素T,成功返回true |
boolean removeAll(Collection<?>) | 删除参数中的所有参数 |
boolean retainAll(Collection<?>) | 删除不包含在参数中容器中的所有参数 |
void clear() | 移除所有元素 |
- 转换类
方法 | 解释 |
---|---|
Object[] toArray() | 返回一个数组,该数组包含容器中所有元素 |
<T> T[] removeAll(T[] a) | 返回一个数组,该数组包含容器中所有元素,返回结果与运行时相同,而不是相同的Object |
boolean retainAll(Collection<?>) | 删除不包含在参数中容器中的所有参数 |
17.4 可选操作
执行不同的添加和移除方法在Collection接口中都是可选操作。这意味着实现类并不需要为这些方法提供定义功能。当调用未被实现的方法时会抛出UnsupportedOperation异常。这样做的目的是防止接口爆炸。
17.5 List功能方法
List有专用的listIterator。
public static void iterMotion(List<String> a) {
ListIterator<String> it = a.listIterator();
b = it.hasNext();
b = it.hasPrevious();
s = it.next();
i = it.nextIndex();
s = it.previous();
i = it.previousIndex();
}
17.6 Set和存储顺序
Set(interface) | Set内的元素是唯一的。加入Set的元素必须定义equals方法以确保对象的唯一性。Set不保证插入元素的顺序 |
HashSet | 为了快速查找而设计的Set,存入HashSet的元素必须定义hashCode() |
TreeSet | 保持次序的Set。元素必须事先Comparable接口 |
LinkedHashSet | 具有HashSet的查询速度,且内部使用链表维护元素的顺序。元素也必须定义hashCode方法 |
17.6.1 SortedSet
Sorted提供了额外的操作:
- Object first()
- Object last()
- SortedSet subSet(from, to)
- SortedSet headSet(to)
- SortedSet tailSet(from)
17.7 队列
17.1.1 优先级队列
PriorityQueue需要类实现Comparable接口
17.2.2 双向队列
双向队列,可以在忍一段添加或移除元素。LinkedList包含支持双向队列的方法。
17.8 理解Map
HashMap | Map基于散列表的实现,可以通过构造器设置容量和负载因子,以调整容器的性能。 |
LinkedHashMap | Map基于散列表的实现。 取键值对的顺序是插入顺序或者最近最少使用的次序(LRU) |
TreeMap | 基于红黑树的实现。查看“键”或“键值对”时,他们会被排序。需要元素具有Comparable接口。 |
WeakHashMap | 弱键映射,允许释放所指对象。当映射之外不存在引用指向某个“键”,则此键可以被垃圾收集器回收。 |
ConcurrentHashMap | 一种线程安全的Map,它不涉及同步加锁 |
IdentityHashMap | 使用==代替equals()对“键”进行比较,为解决特殊问题而设计 |
17.9 散列与散列码
17.9.2 为速度而散列
数组并不保存键本身,而是通过键生成一个数字,将其作为数组的下标。这个数字就是散列码。Object中有hashCode方法,可被覆盖。
由于散列的槽位(slot)通常被称为桶位(bucket)。为了使散列分布均匀,通道的数量通常是质数。
但对现代处理起来说,除法和求余是最慢的操作。使用2的整数次方长度的散列表,可用掩码代替除法。
17.9.3 覆盖hashCode
17.10 选择接口的不同实现
- List的选择
- Set:HashSet最好用,LinkedHashSet保持了元素的插入顺序;TreeSet保持了元素的顺序。
17.11 实用方法
java.utils.Collections类内部有大量用于容器的实用方法。
方法 | 简介 |
---|---|
min(Collection)/max(Collection) | 返回集合内的最大/小元素 |
min(Collection, Comparator)/max(Collection, Comparator) | 根据比较器返回最大/最小元素 |
indexOfSubList(List source, List target) | 返回target在source中第一次出现的位置,失败返回-1 |
lastIndexOfSubList(List source, List target) | 返回target在source中最后一次出现的位置,失败返回-1 |
replaceALL(List<T>, T oldVal, T newVal) | 替换 |
reverse(List) | 逆转所有元素的顺序 |
rotate(List, int distance) | 全体元素后移distance个位置,将末尾的元素循环到前面来 |
Shuffle(List), Shuffle(List, Random) | 随机打乱列表顺序 |
sort(List<T>/sort(List<T>, Comparator<? Super T>) | 自然排序 |
copy(List<? super T> dest, List<? super T> src) | 将src中的元素复制到dest中 |
swap(List, int i, int j) | 交换元素位置,比自己写的代码快 |
fill(List<? super T>, T x) | 用对象x替换list中所有元素 |
nCopies(int n, T x) | 返回大小为n的List<T>,此List不可改变,其中的引用都指向x |
frequency(Collection, T x) | 返回Collection中元素x的个数 |
17.12 持有对象
java.lang.ref中有三个继承自Reference的类:SoftReference、WeakReference和PhantomReference。该三个类别为垃圾回收器提供了不同级别的指示,排列顺序由弱到强。
import java.lang.ref.*;
import java.util.*;
class VeryBig {
private static final int SIZE = 10000;
private long[] la = new long[SIZE];
private String ident;
public VeryBig(String id) { ident = id; }
public String toString() { return ident; }
protected void finalize() {
System.out.println("Finalizing " + ident);
}
}
public class References {
private static ReferenceQueue<VeryBig> rq =
new ReferenceQueue<VeryBig>();
public static void checkQueue() {
Reference<? extends VeryBig> inq = rq.poll();
if(inq != null)
System.out.println("In queue: " + inq.get());
}
public static void main(String[] args) {
int size = 10;
// Or, choose size via the command line:
if(args.length > 0)
size = new Integer(args[0]);
LinkedList<SoftReference<VeryBig>> sa =
new LinkedList<SoftReference<VeryBig>>();
for(int i = 0; i < size; i++) {
sa.add(new SoftReference<VeryBig>(
new VeryBig("Soft " + i), rq));
System.out.println("Just created: " + sa.getLast());
checkQueue();
}
LinkedList<WeakReference<VeryBig>> wa =
new LinkedList<WeakReference<VeryBig>>();
for(int i = 0; i < size; i++) {
wa.add(new WeakReference<VeryBig>(
new VeryBig("Weak " + i), rq));
System.out.println("Just created: " + wa.getLast());
checkQueue();
}
SoftReference<VeryBig> s =
new SoftReference<VeryBig>(new VeryBig("Soft"));
WeakReference<VeryBig> w =
new WeakReference<VeryBig>(new VeryBig("Weak"));
System.gc();
LinkedList<PhantomReference<VeryBig>> pa =
new LinkedList<PhantomReference<VeryBig>>();
for(int i = 0; i < size; i++) {
pa.add(new PhantomReference<VeryBig>(
new VeryBig("Phantom " + i), rq));
System.out.println("Just created: " + pa.getLast());
checkQueue();
}
}
} /*
Just created: java.lang.ref.SoftReference@2ff4acd0
Just created: java.lang.ref.SoftReference@54bedef2
Just created: java.lang.ref.SoftReference@5caf905d
Just created: java.lang.ref.SoftReference@27716f4
Just created: java.lang.ref.SoftReference@8efb846
Just created: java.lang.ref.SoftReference@2a84aee7
Just created: java.lang.ref.SoftReference@a09ee92
Just created: java.lang.ref.SoftReference@30f39991
Just created: java.lang.ref.SoftReference@452b3a41
Just created: java.lang.ref.SoftReference@4a574795
Just created: java.lang.ref.WeakReference@f6f4d33
Just created: java.lang.ref.WeakReference@23fc625e
Just created: java.lang.ref.WeakReference@3f99bd52
Just created: java.lang.ref.WeakReference@4f023edb
Just created: java.lang.ref.WeakReference@3a71f4dd
Just created: java.lang.ref.WeakReference@7adf9f5f
Just created: java.lang.ref.WeakReference@85ede7b
Just created: java.lang.ref.WeakReference@5674cd4d
Just created: java.lang.ref.WeakReference@63961c42
Just created: java.lang.ref.WeakReference@65b54208
Finalizing Weak 3
Just created: java.lang.ref.PhantomReference@1be6f5c3
Finalizing Weak 2
In queue: null
Finalizing Weak 1
Just created: java.lang.ref.PhantomReference@6b884d57
Finalizing Weak 0
In queue: null
Finalizing Weak
Just created: java.lang.ref.PhantomReference@38af3868
Finalizing Weak 9
In queue: null
Finalizing Weak 8
Finalizing Weak 7
Just created: java.lang.ref.PhantomReference@77459877
Finalizing Weak 6
Finalizing Weak 5
Finalizing Weak 4
In queue: null
Just created: java.lang.ref.PhantomReference@5b2133b1
In queue: null
Just created: java.lang.ref.PhantomReference@72ea2f77
In queue: null
Just created: java.lang.ref.PhantomReference@33c7353a
In queue: null
Just created: java.lang.ref.PhantomReference@681a9515
In queue: null
Just created: java.lang.ref.PhantomReference@3af49f1c
In queue: null
Just created: java.lang.ref.PhantomReference@19469ea2
In queue: null
*///:~