集合底层源码

Collection

List

ArrayList

public abstract class AbstractList<E>{//操作数protected transient int modCount = 0;//1
}
​
public class ArrayList<E> extends AbstractList<E> implements List<E>{//空数组的实例(长度为0的数组实例)private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//空数组的实例(长度为0的数组实例)private static final Object[] EMPTY_ELEMENTDATA = {};//元素的容器transient Object[] elementData; //new Object[10]//元素个数(指针)private int size;//10//默认初始化容量private static final int DEFAULT_CAPACITY = 10;//数组最大容量private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}public boolean add(E e) {ensureCapacityInternal(size + 1);//判断是否扩容elementData[size++] = e;return true;}//minCapacity - 11private void ensureCapacityInternal(int minCapacity) {//使用无参构造创建ArrayList时,第一次添加元素时进入此判断if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}ensureExplicitCapacity(minCapacity);}//minCapacity - 11private void ensureExplicitCapacity(int minCapacity) {modCount++;//目的扩容长度必须比数组长度大if (minCapacity - elementData.length > 0)grow(minCapacity);//扩容的方法}//minCapacity - 11private void grow(int minCapacity) {//oldCapacity - 10int oldCapacity = elementData.length;//newCapacity - 15int newCapacity = oldCapacity + (oldCapacity >> 1);//ArrayList扩容机制if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);elementData = Arrays.copyOf(elementData, newCapacity);}private static int hugeCapacity(int minCapacity) {if (minCapacity < 0)throw new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}
}
​

场景:

ArrayList<String> list = new ArrayList<>();list.add("麻生希");list.add("椎名空");list.add("爱田奈奈");list.add("三上悠亚");

LinkedList

public abstract class AbstractList<E>{//操作数protected transient int modCount = 0;
}
public abstract class AbstractSequentialList<E> extends AbstractList<E> {
}
​
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>{//元素个数transient int size = 0;//第一个节点transient Node<E> first;//null//最后一个节点transient Node<E> last;//nullpublic LinkedList() {}public boolean add(E e) {linkLast(e);return true;}void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;modCount++;}//节点类private static class Node<E> {E item; ------- 元素(项)Node<E> next; - 下一个节点地址Node<E> prev; - 上一个节点地址
​Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}}
​}

场景

    LinkedList<String> list = new LinkedList<>();//添加元素list.add("林成");list.add("卢永刚");list.add("李科");

Set

HashSet

public class HashSet<E> extends AbstractSet<E> implements Set<E>{private transient HashMap<E,Object> map;//占位符private static final Object PRESENT = new Object();public HashSet() {map = new HashMap<>();}public boolean add(E e) {return map.put(e, PRESENT)==null;}
}

场景

//HashSet底层由HashMap实现,元素存在HashMap中key的位置
​
HashSet<Student> set = new HashSet<>();
​
//key-new Student("林成", "2107", "001") value-PRESENT
set.add(new Student("林成", "2107", "001"));
​
key-new Student("卢永刚", "2107", "002") value-PRESENT
set.add(new Student("卢永刚", "2107", "002"));
​

TreeSet

//TreeSet底层由TreeMap实现,元素存在TreeMap中key的位置

public interface SortedSet<E> extends Set<E> {}
​
public interface NavigableSet<E> extends SortedSet<E> {}
​
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>{private transient NavigableMap<E,Object> m;//没用的占位符private static final Object PRESENT = new Object();public TreeSet() {this(new TreeMap<E,Object>());}public TreeSet(Comparator<? super E> comparator) {this(new TreeMap<>(comparator));}TreeSet(NavigableMap<E,Object> m) {this.m = m;}public boolean add(E e) {return m.put(e, PRESENT)==null;}
}
​

场景1:

TreeSet<Student> set = new TreeSet<>();set.add(new Student("麻生希", '女', 26, "2107", "001"));
set.add(new Student("北岛玲", '女', 31, "2107", "002"));
set.add(new Student("水菜类", '女', 29, "2107", "003"));

场景2:

TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
​@Overridepublic int compare(Student o1, Student o2) {if(o1.equals(o2)){return 0;}if(o1.getName().length() != o2.getName().length()){return o1.getName().length() - o2.getName().length();}if(o1.getAge() != o2.getAge()){return o1.getAge() - o2.getAge();}return 1;}});set.add(new Student("吉泽明步", '女', 27, "2108", "002"));
set.add(new Student("三上悠亚", '女', 24, "2108", "003"));
set.add(new Student("麻生希", '女', 26, "2107", "001"));

Map

HashMap

HashMap理解题:

​
public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>{//操作数transient int modCount;//3//空数组的实例(长度为0的数组)static final Entry<?,?>[] EMPTY_TABLE = {};//存入数据的容器(hash数组/hash表) --  new Entry[16];transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;//数组默认初始化容量(必须是2的幂)static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//16//默认负载因子static final float DEFAULT_LOAD_FACTOR = 0.75f;//数组最大长度static final int MAXIMUM_CAPACITY = 1 << 30;//映射关系个数transient int size;//3//阈值int threshold;//12//负载因子final float loadFactor;//0.75//hash种子数transient int hashSeed = 0;public HashMap() {this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);}//initialCapacity - 16//loadFactor - 0.75public HashMap(int initialCapacity, float loadFactor) {if (initialCapacity < 0)throw new IllegalArgumentException("Illegal initial capacity: " +initialCapacity);if (initialCapacity > MAXIMUM_CAPACITY)initialCapacity = MAXIMUM_CAPACITY;if (loadFactor <= 0 || Float.isNaN(loadFactor))//NaN - Not a Numberthrow new IllegalArgumentException("Illegal load factor: " +loadFactor);
​this.loadFactor = loadFactor;threshold = initialCapacity;init();}//key - null//value - '女'public V put(K key, V value) {//第一次添加元素时,进入此判断if (table == EMPTY_TABLE) {inflateTable(threshold);//阈值-12,数组初始化,获取hashSeed}if (key == null)return putForNullKey(value);//获取在key的hash+散列算法int hash = hash(key);//通过hash值计算出在数组中的下标int i = indexFor(hash, table.length);//e - 卢永刚的Entryfor (Entry<K,V> e = table[i]; e != null; e = e.next) {Object k;if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {//oldValue - 男V oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue;//key相同,返回被覆盖的value值}}
​modCount++;addEntry(hash, key, value, i);return null;}//添加null键的方法private V putForNullKey(V value) {//e - 0x004for (Entry<K,V> e = table[0]; e != null; e = e.next) {if (e.key == null) {//oldValue - 男V oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue;//返回被覆盖的value值}}modCount++;addEntry(0, null, value, 0);return null;}// hash- 0// key- null// value-'男'//bucketIndex-0void addEntry(int hash, K key, V value, int bucketIndex) {//判断是否扩容if ((size >= threshold) && (null != table[bucketIndex])) {//扩容resize(2 * table.length);//重新计算hash值hash = (null != key) ? hash(key) : 0;//重新计算在数组中的下标bucketIndex = indexFor(hash, table.length);}
​createEntry(hash, key, value, bucketIndex);}//newCapacity - 32void resize(int newCapacity) {Entry[] oldTable = table;//oldCapacity - 16int oldCapacity = oldTable.length;if (oldCapacity == MAXIMUM_CAPACITY) {threshold = Integer.MAX_VALUE;return;}
​//创建新的hash数组Entry[] newTable = new Entry[newCapacity];//initHashSeedAsNeeded(newCapacity)根据新数组的容量重新计算hash种子数transfer(newTable, initHashSeedAsNeeded(newCapacity));//将原数据迁移到新数组中//新数组的地址赋值给老数组table = newTable;//重新计算阈值threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);}void transfer(Entry[] newTable, boolean rehash) {int newCapacity = newTable.length;for (Entry<K,V> e : table) {while(null != e) {Entry<K,V> next = e.next;if (rehash) {e.hash = null == e.key ? 0 : hash(e.key);}int i = indexFor(e.hash, newCapacity);e.next = newTable[i];newTable[i] = e;e = next;}}}// hash- 0// key- null// value-'男'// bucketIndex-0void createEntry(int hash, K key, V value, int bucketIndex) {//e - nullEntry<K,V> e = table[bucketIndex];table[bucketIndex] = new Entry<>(hash, key, value, e);size++;}static int indexFor(int h, int length) {return h & (length-1);}final int hash(Object k) {int h = hashSeed;if (0 != h && k instanceof String) {//key为String类型时,回去的hash值是有hash种子数参与的return sun.misc.Hashing.stringHash32((String) k);}
​h ^= k.hashCode();
​h ^= (h >>> 20) ^ (h >>> 12);return h ^ (h >>> 7) ^ (h >>> 4);}//toSize - 16private void inflateTable(int toSize) {//capacity - 16int capacity = roundUpToPowerOf2(toSize);//不管传什么int数据,都返回与之对应的2的幂//threshold - 12threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);//初始化数组table = new Entry[capacity];//初始化hash种子数initHashSeedAsNeeded(capacity);}final boolean initHashSeedAsNeeded(int capacity) {boolean currentAltHashing = hashSeed != 0;boolean useAltHashing = sun.misc.VM.isBooted() &&(capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);boolean switching = currentAltHashing ^ useAltHashing;if (switching) {hashSeed = useAltHashing? sun.misc.Hashing.randomHashSeed(this): 0;}return switching;}private static int roundUpToPowerOf2(int number) {return number >= MAXIMUM_CAPACITY? MAXIMUM_CAPACITY: (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;}
​//映射关系类/节点类static class Entry<K,V> implements Map.Entry<K,V> {final K key; ---- keyV value; -------- 值Entry<K,V> next;- 下一个节点的地址int hash; ------- key的hash值
​Entry(int h, K k, V v, Entry<K,V> n) {value = v;next = n;key = k;hash = h;}}
}

场景: HashMap<Student, Character> map = new HashMap<>();

    map.put(new Student("林成", "2107", "001"), '男');map.put(new Student("李科", "2107", "002"), '男');Student stu = new Student("卢永刚", "2107", "003");map.put(stu, '男');Character put = map.put(stu, '女');System.out.println(put);map.put(null, '男');map.put(null, '女');

TreeMap

public interface SortedMap<K,V> extends Map<K,V> {}
​
public interface NavigableMap<K,V> extends SortedMap<K,V> {}
​
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>{
//外置比较器
private Comparator comparator;
//根节点
private transient Entry<K,V> root;
//元素个数
private transient int size = 0;
//操作数
private transient int modCount = 0;
​
public TreeMap(){comparator = null;
}
​
public TreeMap(Comparator comparator){this.comparator = comparator;
}
​
//key - new Student("卢永刚", '男', 29, "2107", "003")
//value - '男'
public V put(K key, V value) {//t - 林成的EntryEntry<K,V> t = root;//第一次添加元素时进入的判断if (t == null) {//key自己判断自己,目的检查Key是否为null和key所属的类是否实现Comparable接口compare(key, key);
​root = new Entry<>(key, value, null);size=1;modCount++;return null;}//比较结果int cmp;//父节点的变量Entry<K,V> parent;//获取外置比较器Comparator<? super K> cpr = comparator;if (cpr != null) {//执行外置比较器的排序规则 - compare()do {parent = t;cmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}else {//执行内置比较器的排序规则 - compareTo()if (key == null)throw new NullPointerException();@SuppressWarnings("unchecked")// k - 卢永刚的Student对象Comparable<? super K> k = (Comparable<? super K>) key;//cmp - -2do {//parent - 李科的Entryparent = t;cmp = k.compareTo(t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}//e - Entry<K,V> e = new Entry<>(key, value, parent);if (cmp < 0)parent.left = e;elseparent.right = e;//红黑树的制衡fixAfterInsertion(e);size++;modCount++;return null;
}
​
@SuppressWarnings("unchecked")
final int compare(Object k1, Object k2) {return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2): comparator.compare((K)k1, (K)k2);
}
​
static final class Entry<K,V> implements Map.Entry<K,V> {K key;  ---------- keyV value; --------- valueEntry<K,V> left; - 左边节点地址Entry<K,V> right;- 右边节点地址Entry<K,V> parent; - 父节点地址boolean color = BLACK;
​Entry(K key, V value, Entry<K,V> parent) {this.key = key;this.value = value;this.parent = parent;}
}

场景1:

TreeMap<Student, Character> map = new TreeMap<>();map.put(new Student("林成", '男', 26, "2107", "001"),'男');
map.put(new Student("李科", '男', 31, "2107", "002"),'男');
map.put(new Student("卢永刚", '男', 29, "2107", "003"),'男');

场景2:

TreeMap<Student,Character> map = new TreeMap<>(new Comparator<Student>() {
​@Overridepublic int compare(Student o1, Student o2) {if(o1.equals(o2)){return 0;}if(o1.getName().length() != o2.getName().length()){return o1.getName().length() - o2.getName().length();}if(o1.getAge() != o2.getAge()){return o1.getAge() - o2.getAge();}return 1;}});map.put(new Student("林成", '男', 26, "2107", "001"),'男');
map.put(new Student("李科", '男', 31, "2107", "002"),'男');
map.put(new Student("卢永刚", '男', 29, "2107", "003"),'男');

比较器的优先级别:外置比较器>内置比较器

内置比较器-Comparable:compareTo()

外置比较器-Comparator:compare()

Java集合框架底层源码相关推荐

  1. 死磕Java集合之BitSet源码分析(JDK18)

    死磕Java集合之BitSet源码分析(JDK18) 文章目录 死磕Java集合之BitSet源码分析(JDK18) 简介 继承体系 存储结构 源码解析 属性 构造方法 set(int bitInde ...

  2. 死磕 java集合之ArrayDeque源码分析

    问题 (1)什么是双端队列? (2)ArrayDeque是怎么实现双端队列的? (3)ArrayDeque是线程安全的吗? (4)ArrayDeque是有界的吗? 简介 双端队列是一种特殊的队列,它的 ...

  3. idea 线程内存_Java线程池系列之-Java线程池底层源码分析系列(一)

    课程简介: 课程目标:通过本课程学习,深入理解Java线程池,提升自身技术能力与价值. 适用人群:具有Java多线程基础的人群,希望深入理解线程池底层原理的人群. 课程概述:多线程的异步执行方式,虽然 ...

  4. idea 线程内存_Java线程池系列之-Java线程池底层源码分析系列(二)

    课程简介: 课程目标:通过本课程学习,深入理解Java线程池,提升自身技术能力与价值. 适用人群:具有Java多线程基础的人群,希望深入理解线程池底层原理的人群. 课程概述:多线程的异步执行方式,虽然 ...

  5. Java集合之TreeMap源码解析上篇

    上期回顾 上期我从树型结构谈到了红黑树的概念以及自平衡的各种变化(指路上期←戳),本期我将会对TreeMap结合红黑树理论进行解读. 首先,我们先来回忆一下红黑树的5条基本规则. 1.结点是红色或者黑 ...

  6. 【死磕 Java 集合】— LinkedTransferQueue源码分析

    [死磕 Java 集合]- LinkedTransferQueue源码分析 问题 (1)LinkedTransferQueue是什么东东? (2)LinkedTransferQueue是怎么实现阻塞队 ...

  7. java arraydeque_死磕 java集合之ArrayDeque源码分析

    问题 (1)什么是双端队列? (2)ArrayDeque是怎么实现双端队列的? (3)ArrayDeque是线程安全的吗? (4)ArrayDeque是有界的吗? 简介 双端队列是一种特殊的队列,它的 ...

  8. Java集合框架底层原理

    Java集合框架 Java集合框架 List集合 ArrayList底层实现原理 ArrayList数组扩容技术(数组拷贝) 扩容大小 查询和删除 集合中的泛型 LinkedList Vector 线 ...

  9. Java集合系列---Collection源码解析及整体框架结构

    集合的整体框架结构及依赖关系 1.Collection public interface Collection<E> extends Iterable<E> {} Collec ...

最新文章

  1. 阿里团队最新实践:如何解决大规模分类问题?
  2. 拦截推送信息_Android10.0公测版H2OS For OnePlus 6T第1版已推送更新
  3. 78. Leetcode 264. 丑数 II (堆-技巧二-多路归并)
  4. RDA8955的新版本SDK串口接收数据的问题记录
  5. C++封装常用对象和对头文件以及预编译机制的探索
  6. 谷歌Pixel 4真机曝光:宽大额头内含诸多玄机
  7. 详细叙述ajax的详情,ajax的配置详情、ajax的调用解释、ajax的中文乱码和ajax的表单提交(内有实例)...
  8. matlab图像处理Lena大作业
  9. 英威腾GD200A系列变频器实现多段速控制的相关参数设置及接线
  10. 【微信小程序】自定义导航栏
  11. 简析发送手机验证码原理
  12. c语言if语句知识点总结,c语言中if语句知识点总结
  13. printf如何按二进制格式打印
  14. 【hdu4609】 3-idiots FFT
  15. 单片机笔记(江科大自化协)
  16. 混沌数学之Chua's circuit(蔡氏电路)
  17. SD-scard-对应CMD指令集讲解
  18. Windows 10驱动签名_win 10驱动数字签名_驱动签名注意事项
  19. 如何u盘安装Linux系统CentOS7.2
  20. ibeacon和微信周边介绍

热门文章

  1. 【FPGA】MicroBlaze小试01-串口输出Hello World(demo,熟悉开发流程)
  2. luo3372线段树模板的分块做法
  3. Android uevent 电池电量上报机制
  4. 读书笔记之《支付战争》
  5. 就当做LaTeX练习(
  6. web前端动态环形时钟demo练习
  7. 物联网传感技术——谐振式传感器
  8. threejs 3d
  9. Java Selenium简单浏览器模拟
  10. murmurhash java_默默hash(MurmurHash)