static class Node implements Map.Entry {
// 常量 hash 值
final int hash;
// 常量 key 值
final K key;
// value 值
V value;
// Node 类型的 next
Node next;
// 有参构造函数
Node(int hash, K key, V value, Node next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
// 公共的方法 获取 Node 的属性 key 和 value 的值
public final K getKey() { return key; }
public final V getValue() { return value; }
// 重写了 toString 方法
public final String toString() { return key + "=" + value; }
// 重写了 hashCode 方法
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
// 刚刚的 修改 value 的方法
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
// 重写了 equals 方法
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry,?> e = (Map.Entry,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
public class LinkedHashMap
extends HashMap
implements Map
{
static class Entry extends HashMap.Node {
Entry before, after;
Entry(int hash, K key, V value, Node next) {
super(hash, key, value, next);
}
}
private static final long serialVersionUID = 3801124242820219131L;
transient LinkedHashMap.Entry head;
transient LinkedHashMap.Entry tail;
final boolean accessOrder;
private void linkNodeLast(LinkedHashMap.Entry p) {
LinkedHashMap.Entry last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}
private void transferLinks(LinkedHashMap.Entry src,
LinkedHashMap.Entry dst) {
LinkedHashMap.Entry b = dst.before = src.before;
LinkedHashMap.Entry a = dst.after = src.after;
if (b == null)
head = dst;
else
b.after = dst;
if (a == null)
tail = dst;
else
a.before = dst;
}
void reinitialize() {
super.reinitialize();
head = tail = null;
}
Node newNode(int hash, K key, V value, Node e) {
LinkedHashMap.Entry p =
new LinkedHashMap.Entry(hash, key, value, e);
linkNodeLast(p);
return p;
}
Node replacementNode(Node p, Node next) {
LinkedHashMap.Entry q = (LinkedHashMap.Entry)p;
LinkedHashMap.Entry t =
new LinkedHashMap.Entry(q.hash, q.key, q.value, next);
transferLinks(q, t);
return t;
}
TreeNode newTreeNode(int hash, K key, V value, Node next) {
TreeNode p = new TreeNode(hash, key, value, next);
linkNodeLast(p);
return p;
}
TreeNode replacementTreeNode(Node p, Node next) {
LinkedHashMap.Entry q = (LinkedHashMap.Entry)p;
TreeNode t = new TreeNode(q.hash, q.key, q.value, next);
transferLinks(q, t);
return t;
}
void afterNodeRemoval(Node e) { // unlink
LinkedHashMap.Entry p =
(LinkedHashMap.Entry)e, b = p.before, a = p.after;
p.before = p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a == null)
tail = b;
else
a.before = b;
}
void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
void afterNodeAccess(Node e) { // move node to last
LinkedHashMap.Entry last;
if (accessOrder && (last = tail) != e) {
LinkedHashMap.Entry p =
(LinkedHashMap.Entry)e, b = p.before, a = p.after;
p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a != null)
a.before = b;
else
last = b;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
for (LinkedHashMap.Entry e = head; e != null; e = e.after) {
s.writeObject(e.key);
s.writeObject(e.value);
}
}
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
public LinkedHashMap() {
super();
accessOrder = false;
}
public LinkedHashMap(Map extends K, ? extends V> m) {
super();
accessOrder = false;
putMapEntries(m, false);
}
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
public boolean containsValue(Object value) {
for (LinkedHashMap.Entry e = head; e != null; e = e.after) {
V v = e.value;
if (v == value || (value != null && value.equals(v)))
return true;
}
return false;
}
public V get(Object key) {
Node e;
if ((e = getNode(hash(key), key)) == null)
return null;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
public V getOrDefault(Object key, V defaultValue) {
Node e;
if ((e = getNode(hash(key), key)) == null)
return defaultValue;
if (accessOrder)
afterNodeAccess(e);
return e.value;
}
public void clear() {
super.clear();
head = tail = null;
}
protected boolean removeEldestEntry(Map.Entry eldest) {
return false;
}
public Set keySet() {
Set ks = keySet;
if (ks == null) {
ks = new LinkedKeySet();
keySet = ks;
}
return ks;
}
final class LinkedKeySet extends AbstractSet {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator iterator() {
return new LinkedKeyIterator();
}
public final boolean contains(Object o) { return containsKey(o); }
public final boolean remove(Object key) {
return removeNode(hash(key), key, null, false, true) != null;
}
public final Spliterator spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED |
Spliterator.DISTINCT);
}
public final void forEach(Consumer super K> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
action.accept(e.key);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
public Collection values() {
Collection vs = values;
if (vs == null) {
vs = new LinkedValues();
values = vs;
}
return vs;
}
final class LinkedValues extends AbstractCollection {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator iterator() {
return new LinkedValueIterator();
}
public final boolean contains(Object o) { return containsValue(o); }
public final Spliterator spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED);
}
public final void forEach(Consumer super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
action.accept(e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
public Set> entrySet() {
Set> es;
return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
}
final class LinkedEntrySet extends AbstractSet> {
public final int size() { return size; }
public final void clear() { LinkedHashMap.this.clear(); }
public final Iterator> iterator() {
return new LinkedEntryIterator();
}
public final boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry,?> e = (Map.Entry,?>) o;
Object key = e.getKey();
Node candidate = getNode(hash(key), key);
return candidate != null && candidate.equals(e);
}
public final boolean remove(Object o) {
if (o instanceof Map.Entry) {
Map.Entry,?> e = (Map.Entry,?>) o;
Object key = e.getKey();
Object value = e.getValue();
return removeNode(hash(key), key, value, true, true) != null;
}
return false;
}
public final Spliterator> spliterator() {
return Spliterators.spliterator(this, Spliterator.SIZED |
Spliterator.ORDERED |
Spliterator.DISTINCT);
}
public final void forEach(Consumer super Map.Entry> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
action.accept(e);
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
public void forEach(BiConsumer super K, ? super V> action) {
if (action == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
action.accept(e.key, e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
public void replaceAll(BiFunction super K, ? super V, ? extends V> function) {
if (function == null)
throw new NullPointerException();
int mc = modCount;
for (LinkedHashMap.Entry e = head; e != null; e = e.after)
e.value = function.apply(e.key, e.value);
if (modCount != mc)
throw new ConcurrentModificationException();
}
abstract class LinkedHashIterator {
LinkedHashMap.Entry next;
LinkedHashMap.Entry current;
int expectedModCount;
LinkedHashIterator() {
next = head;
expectedModCount = modCount;
current = null;
}
public final boolean hasNext() {
return next != null;
}
final LinkedHashMap.Entry nextNode() {
LinkedHashMap.Entry e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
current = e;
next = e.after;
return e;
}
public final void remove() {
Node p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
K key = p.key;
removeNode(hash(key), key, null, false, false);
expectedModCount = modCount;
}
}
final class LinkedKeyIterator extends LinkedHashIterator
implements Iterator {
public final K next() { return nextNode().getKey(); }
}
final class LinkedValueIterator extends LinkedHashIterator
implements Iterator {
public final V next() { return nextNode().value; }
}
final class LinkedEntryIterator extends LinkedHashIterator
implements Iterator> {
public final Map.Entry next() { return nextNode(); }
}
}
有一个重载方法:void sort(List list, Comparator super T> c) 这个方法第二个参数是传入一个Comparator 实现类对象,这个方法就不要求一定要实现Comparable接口了。即使实现了,也是按照Comparator中定义的比较方法进行排序。
List list = new ArrayList<>();
list.add(123);
list.add(34);
list.add(7);
list.add(12);
list.add(-8);
list.add(0);
System.out.println(list);// [123, 34, 7, 12, -8, 0]
Collections.sort(list);
System.out.println(list); // [-8, 0, 7, 12, 34, 123]
void swap(List> list, int i, int j) 交换list的指定索引的元素,对原List操作
List list = new ArrayList<>();
list.add(123);
list.add(34);
list.add(7);
list.add(12);
list.add(-8);
list.add(0);
System.out.println(list);// [123, 34, 7, 12, -8, 0]
Collections.swap(list, 2,5);
System.out.println(list); // [123, 34, 0, 12, -8, 7]
T max(Collection extends T> coll) 求 List中的最大元素,按照 Comparable接口进行比较
T max(Collection extends T> coll, Comparator super T> comp) 求 List中的最大元素,按照 Comparator接口进行比较
T min(Collection extends T> coll) 求 List中的最小元素,按照 Comparable接口进行比较
T min(Collection extends T> coll, Comparator super T> comp) 求 List中的最小元素,按照 Comparator接口进行比较
List list = new ArrayList<>();
list.add(123);
list.add(34);
list.add(7);
list.add(12);
list.add(-8);
list.add(0);
System.out.println(list);
Comparable max = Collections.max(list);
Comparable min = Collections.min(list);
System.out.println(max); // 123
System.out.println(min); // -8
int frequency(Collection> c, Object o) 找到指定的元素在List中出现的次数,返回值是int型
List list = new ArrayList<>();
list.add(123);
list.add(34);
list.add(7);
list.add(34);
list.add(12);
list.add(-8);
list.add(0);
int i = Collections.frequency(list, 34);
int i1 = Collections.frequency(list, 9);
System.out.println(i); // 2
System.out.println(i1); // 0
void copy(List super T> dest, List extends T> src) 复制List,第一参数是 目标List,第二个参数是 源List
下面是 copy方法的源码:
public static void copy(List super T> dest, List extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i di=dest.listIterator();
ListIterator extends T> si=src.listIterator();
for (int i=0; i
可以看到 源List的长度 不能大于 目标 List的长度,否则会抛异常。
下面这种写法就会有异常:原因是 直接new的List 长度为 0
List list = new ArrayList<>();
List list1 = new ArrayList<>();
list.add(123);
list.add(34);
list.add(7);
list.add(34);
list.add(12);
list.add(-8);
list.add(0);
Collections.copy(list1, list); // 异常:IndexOutOfBoundsException: Source does not fit in dest
System.out.println(list1);
List list = new ArrayList<>();
list.add(123);
list.add(34);
list.add(7);
list.add(34);
list.add(12);
list.add(-8);
list.add(0);
// 得到线程安全的 list
List list1 = Collections.synchronizedList(list);
lua:
local access_token = ngx.var.cookie_SGAccessToken
if access_token then
ngx.header["Set-Cookie"] = "SGAccessToken="..access_token.."; path=/;Max-Age=3000"
end