Java集合类的底层实现探索
List:
ArrayList
首先我们来看看jdk的ArrayList的add方法的源码是如何实现的:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
在AarryList类有如下数组的定义
/**
* The array buffer into which the elements of the ArrayList are stored. --这是个存储ArrayList元素的数组
* The capacity of the ArrayList is the length of this array buffer. ---ArrayList的长度即是数组的长度
*/
private transient Object[] elementData;
综上所看,ArrayList底层存储的实现是通过一个数组来实现的
LinkedList
上源码:
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;
/**
* Links e as last element.
*/
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;
else
l.next = newNode;
size++;
modCount++;
}
//在ArrayList内部是有这么一个作为"节点"的内部类的
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底层实现是链表;这里代码只是列举了往集合末尾添加元素的情况,具体看linkLast(E e)这个方法
linkLast方法内会根据参数e生成Node,再根据tail具体情况,修改生成node的pre/next指向,存储形式也就是链表啦
Map:
map的底层实现是 数组+链表
描述一下map存储key-value的过程:
key和value两个对象put到map的时候,会被封装成Entry<K,V>实体对象;put过程会根据K值生成一个hash码值(int类型,不同的key可能会生成相同的hash码)
这个hash码会被当成数组的索引/下标(index),数组的每个下标对应一个hash码,而一个hash码对应一个链表(链表存储着具有相同hash码的对象)
比如: 现在要 map.put("aa","123"); "aa"对应的hash码是121
map.put("bb","123"); "bb"对应的hash码也是121 执行put操作的时候程序会先到数组找到下标为121(也就是hash的数值)的链表,再通过链表存储put进来的对象
具体代码:
/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>.)
*/
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length); //找出数组对应的下标
for (Entry<K,V> e = table[i]; e != null; e = e.next) { //找到数组内对应下标的链表对象
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { //原先key已经存在时,覆盖操作
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);//原先不存在key对应的Entry则在链表后添加
return null;
}
Set
set的特点是无序,不重复
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
以上是HashSet源码,可以看出HashSet底层是通过Map来实现的,不重复实现:e的hash值相同时,Map会采取覆盖的形式,这样就不会有重复了
Map的无序也就自然导致了HashSet的无序了(hash值求法?HashCode与equals)
"打完收工"....
Java集合类的底层实现探索的更多相关文章
- Java集合详解8:Java集合类细节精讲
今天我们来探索一下Java集合类中的一些技术细节.主要是对一些比较容易被遗漏和误解的知识点做一些讲解和补充.可能不全面,还请谅解. 本文参考:http://cmsblogs.com/?cat=5 具体 ...
- java集合类TreeMap和TreeSet
看这篇博客前,可以先看下下列这几篇博客 Red-Black Trees(红黑树) (TreeMap底层的实现就是用的红黑 ...
- Java集合类--温习笔记
最近面试发现自己的知识框架有好多问题.明明脑子里知道这个知识点,流程原理也都明白,可就是说不好,不知道是自己表达技能没点,还是确实是自己基础有问题.不管了,再巩固下基础知识总是没错的,反正最近空闲时间 ...
- Java集合类: Set、List、Map、Queue使用场景梳理
本文主要关注Java编程中涉及到的各种集合类,以及它们的使用场景 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E ...
- Java集合类: Set、List、Map、Queue使用
目录 1. Java集合类基本概念 2. Java集合类架构层次关系 3. Java集合类的应用场景代码 1. Java集合类基本概念 在编程中,常常需要集中存放多个数据.从传统意义上讲,数组是我们的 ...
- 基础知识《六》---Java集合类: Set、List、Map、Queue使用场景梳理
本文转载自LittleHann 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E6%8E%92%E5%BA%8F% ...
- java集合类(五)About Map
接上篇“java集合类(四)About Set” 这次学完Map之后,就剩队列的知识,之后有关java集合类的学习就将告一段落,之后可能会有java连接数据库,I/O,多线程,网络编程或Android ...
- java集合类(四)About Set
接上篇:java集合类(三)About Iterator & Vector(Stack) 之前,在比较java常见集合类的时候,就了解到一点有关Set的特性.实现类及其要求等,读者可以去温习下 ...
- java集合类(三)About Iterator & Vector(Stack)
接上篇:java集合类学习(二) Talk about “Iterator”: 任何容器类,在插入元素后,还需要取回元素,因为这是容器的最基本工作.对于一般的容器,插入有add()相关方法(List, ...
随机推荐
- anujs1.4.0发布
经过三个月的埋头苦干,终于完成Fiber版的anujs. 主要特性有: 测试全部改成jest, 迁移官方测试用例.有许多迷你React吹得怎么天花乱坠,但是生命周期钩子的执行顺序无法与官方保持一致,那 ...
- 提升lua代码效率
local test = {} , do test[ i ] = {} end local t1 = os.clock( ) , do test[ ].mValue = end local t2 = ...
- vue中的一些知识点--多看文档
重温vue,一些知识点简单记录. 1.我们都知道当数据变化时,视图会重新渲染.注意:只有当vue实例被创建时,data中存在的属性才是响应式的.后续新添加的属性不会触发视图变化. 使用 Object. ...
- .net WCF简单练习
之前一直没接触过WCF这个东西,由于是初学WCF没有深入研究其原理,只是写了一个demo WCF服务用于两个不同项目中的调用,在这里我举例项目A调用WCF服务实现查询数据功能. 第一步:创建数据库,有 ...
- 让history显示时间
如何让history显示时间 linux和unix上都提供了history命令,可以查询以前执行的命令历史记录 但是,这个记录并不包含时间项目 因此只能看到命令,但是不知道什么时间执行的 如何让his ...
- CHD 5.15 安装 Kylin
这里主要参考官网安装单机案例,并写入到脚本中.具体请看如下: 1.说明 这里采用的是root用户安装,但是运行时需要改一些配置,不然没有权限 2.安装 ...
- 云笔记项目-MyBatis返回自增类型&堆栈对象补充理解
在云笔记项目中,讲到了MySql的自增,MyBatis查询到自增类型数据后可以设置返回到参数属性,其中学习了MySql的自增写法,堆栈对象等知识. MySql数据类型自增 建立一张Person表,其中 ...
- Java框架spring 学习笔记(十一):aop相关概念
为什么要引入aop? 比如如下情景: 在父类的方法名称发送了变化,在子类调用的方法也需要变化,当工程规模越来越大的时候,维护起来相当不方便,于是就引入了横向切面aop. aop的相关概念: 连接点:类 ...
- JAVA获取客户端请求的当前网络ip地址(附:Nginx反向代理后获取客户端请求的真实IP)
1. JAVA获取客户端请求的当前网络ip地址: /** * 获取客户端请求的当前网络ip * @param request * @return */ public static String get ...
- Charles篡改后台数据
1.打开Charles找到相对应的接口 2.在接口上右键选择Breakpoints打断点. 3.重新请求截断接口,Charles会多弹出一个截断窗口如下图(第一个修改请求的,第二图是修改返回的) 点击 ...