Java 语法的高级操作
LinkedHashMap 有序哈系表
Jdk中的MAP
容器主要有三种实现: 1. HashMap 2. TreeMap 3. LinkedHashMap
HashMap
其key
是完全无序的TreeMap
允许用户定义key
的比较函数(compare函数),因此其key
是根据比较函数排序的LinkedHashMap
在HashMap
基础上,设定了key
的迭代顺序,默认按照插入顺序,也可以设定按照更新顺序
这里主要介绍一下LinkedHashMap
,首先看看其参数最多的构造函数:
/**
* Constructs an empty <tt>LinkedHashMap</tt> instance with the
* specified initial capacity, load factor and ordering mode.
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @param accessOrder the ordering mode - <tt>true</tt> for
* access-order, <tt>false</tt> for insertion-order
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
注意到,accessOrder
参数就是用来设定key
的排序方式
LinkedHashMap
按照key
排序的机制实现是非常简单的,就是在HashMap
的基础上,在每个Entry
上添加了两个‘指针’,分别指向前后两个元素:
/**
* LinkedHashMap entry.
*/
private static class Entry<K,V> extends HashMap.Entry<K,V> {
// These fields comprise the doubly linked list used for iteration.
Entry<K,V> before, after;
...
String.intern()
String.intern()
方法的主要作用在于缩减字符串的存储空间,比如有很多一样的字符串,可以共用intern()方法获取常量池中的字符串对象
由于String
的equals
方法先比较两个字符串的引用地址是否相同,所以str1.intern().equals(str2.intern())
将会十分高效
优先队列
逆序优先队列
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(initCapacity, Collections.reverseOrder());
内部类做Comparater的有限队列:
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(10,
new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);//ascend order
}
});
Shuffle
java.util.Collections
中提供了随机重排数组的方法shuffle(List<?> list)
随机重排算法要求每个元素出现在每个位置的概率相等,随机过程很简单:逆序遍历数组,每次从前n个元素中随机选取一个和第n个交换位置
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
但这里要考虑list是不是可以随机访问的,如果是LinkedList
,则需要先转化为ArrayList
,否则上面的算法需要O(n^2)
的时间复杂度,完整代码如下:
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
Object arr[] = list.toArray();
// Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
// Dump array back into list
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}