Draymonders / Code-Life

The marathon continues though.
27 stars 3 forks source link

Java 源码分析 #101

Closed Draymonders closed 3 years ago

Draymonders commented 3 years ago

先来一波容器和集合,方法按照增删查改列举出来

collection

List

朴素的方法

boolean add(E var1);
boolean addAll(Collection<? extends E> var1);

E remove(int var1);
boolean remove(Object var1);

E get(int var1);
boolean contains(Object var1);

E set(int var1, E var2);

ArrayList

DEFAULT_CAPACITY = 10

int newCapacity = oldCapacity + (oldCapacity >> 1);

LinkedList

// 根据properties推断出是 循环双向链表
transient int size;
transient LinkedList.Node<E> first;
transient LinkedList.Node<E> last;

private static class Node<E> {
  E item;
  LinkedList.Node<E> next;
  LinkedList.Node<E> prev;
}

public void addFirst(E e) 
public void addLast(E e)

public E removeFirst()
public E removeLast()

public E getFirst()
public E getLast()

CopyOnWriteList

适合读多写少的场景

// 分析: 会clone一个新的数组,然后替换引用
public E set(int index, E element) {
  synchronized(this.lock) {
    Object[] es = this.getArray();
    E oldValue = elementAt(es, index);
    if (oldValue != element) {
      es = (Object[])es.clone();
      es[index] = element;
    }
    this.setArray(es);
    return oldValue;
  }
}

// 获取没有锁,所以不一定是最新的值
public E get(int index) {
  return elementAt(this.getArray(), index);
}

Map

HashMap

hash方法,根据hash方法可知,当key为null时,hash(null)=0, 固定插在tab[0]

static final int hash(Object key) {
  int h;
  return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

put方法

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
    boolean evict) {
  Node<K,V>[] tab; Node<K,V> p; int n, i;
  if ((tab = table) == null || (n = tab.length) == 0)
    n = (tab = resize()).length;
  if ((p = tab[i = (n - 1) & hash]) == null)
    tab[i] = newNode(hash, key, value, null);
  else {
    Node<K,V> e; K k;
    if (p.hash == hash &&
        ((k = p.key) == key || (key != null && key.equals(k))))
      e = p;
    else if (p instanceof TreeNode)
      e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
    else {
      for (int binCount = 0; ; ++binCount) {
        if ((e = p.next) == null) {
          p.next = newNode(hash, key, value, null);
          if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
            treeifyBin(tab, hash);
          break;
        }
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
          break;
        p = e;
      }
    }
    if (e != null) { // existing mapping for key
      V oldValue = e.value;
      if (!onlyIfAbsent || oldValue == null)
        e.value = value;
      afterNodeAccess(e);
      return oldValue;
    }
  }
  ++modCount;
  if (++size > threshold)
    resize();
  afterNodeInsertion(evict);
  return null;
}

get方法

final Node<K,V> getNode(int hash, Object key) {
  Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
  if ((tab = table) != null && (n = tab.length) > 0 &&
      (first = tab[(n - 1) & hash]) != null) {
    if (first.hash == hash && // always check first node
        ((k = first.key) == key || (key != null && key.equals(k))))
      return first;
    if ((e = first.next) != null) {
      if (first instanceof TreeNode)
        return ((TreeNode<K,V>)first).getTreeNode(hash, key);
      do {
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
          return e;
      } while ((e = e.next) != null);
    }
  }
  return null;
}

concurrentHashMap

todo

Set

HashSet

todo

TreeSet

todo

Draymonders commented 3 years ago

ThreadLocal

https://www.cnblogs.com/Draymonder/p/10433516.html

ThreadLocal源码

public T get() {
    Thread t = Thread.currentThread();
    // 获取线程的ThreadLocalMap
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        // 根据threadLocal去查找对应的值
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    // 如果没找到就尝试初始化
    return setInitialValue();
}
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        map.set(this, value);
    } else {
        createMap(t, value);
    }
}