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, ...
随机推荐
- 如何系统的学习Java
初学者记住一点,学习Java一定是连续性的且循序渐进的“系统化”学习,首先我给你提供一个优秀Java工程师的学习路线. web前端方面:html.css,Java.jQuery.xml解析.Boots ...
- LR常用函数
web_set_max_html_param_len()--常用函数 设置可检索并保存为参数的任何HTML字符串的最大长度. intweb_set_max_html_param_len(const c ...
- File和FileStream的区别
File和FileStream的区别直观点:File是一个静态类:FileStream是一个非静态类.File:是一个文件的类,对文件进行操作.其内部封装了对文件的各种操作(MSDN:提供用于创建.复 ...
- [原创] 扩展jquery-treegrid插件, 实现勾选功能和全删按钮.
新上手一个项目, 因而正好想学习下bootstrap, 所以就采用asp.net mvc + bootstrap来做. 因为需要TreeGrid的控件, 本来想用easyUI.LingerUi.DW ...
- jquery中的 parseJSON() 源码分析
parseJSON: function( data ) { // Attempt to parse using the native JSON parser first if ( window.JSO ...
- 初始IP协议
一.引言 发送一段TCP数据大致需要经过:用户封装 –> TCP封装 –> IP封装 –>帧封装 Note:用户封装没啥好说的,都是客户自己决定的,在一些简单的应用情况下,这个步骤可 ...
- 项目(七)SVN版本管理与大型代码上线方案
SVN介绍 Svn(subversion)是近年来崛起的非常优秀的版本管理工具,与CVS管理工具一样,SVN是一个跨平台的开源的版本控制系统.Svn版本管理工具管理着随时间改变的各种数据.这些数据放置 ...
- vue axios跨域
现在应用都是前后端分离,这也造成前端在调用接口时出现跨域问题,在控制台会这样提示 ,如果有类似于此图的提示,就已经表明你的接口调用出现了跨域问题,此文章是我对于vue跨域其中一种方式的一些经验,如果错 ...
- antd-react-mobile(踩坑记录)
1.按照官网步骤进行, $ npm install -g create-react-app # 注意:工具会自动初始化一个脚手架并安装 React 项目的各种必要依赖,如果在过程中出现网络问题,请尝试 ...
- pythond的icmp广播报获取局域网主机IP
icmp广播报获取局域网四川特产IP from scapy.all import *import randomimport threading def scan(sip,dip): pkt = Eth ...