java集合框架使用原理分析
集合是我们日常编程中可能用的很多的技术之一 使用频率极高 可能平时就会知道怎么去用 但是集合之间的关系与不同之处都不是很清楚 对它们的底层原理更甚 所以写词文章 让自己有一个更深的认识
集合是一个庞大的家族 今天先来说说这几个 ArrayList、LinkedList、Vector
ArrayList 由于它的底层是数组 数组我们都知道它的查询修改都是效率很高的 ArrayList也是如此 但是为什么查询修改效率高 插入和删除效率低较低呢 这就跟它的数据结构有关系呢 接下啦我们来看看ArrayList数据结构模型
插入、删除:如果我们要想集合中插入一个数100 它的操作步骤是 先在集合中把要插入的位置的数32复制一份 然后再把后面的数往后移 我们不仅要复制数据 而且还要将数据往后移 如果这个集合的数据很多的话 那效率就会很低 进行删除的话后面的数据复制一份 同时数据都要像前面移动 效率也很低
查询、修改: 修改如果进行查询 我们只需要通过数组下标就可以定位到数据 所以效率高 实际开发中 我们大部分是进行查询数据 所以ArrayList使用很广泛
任何事物都有两面性 不管是生活中 还是工作中 在编程也是同样适用的(因为编程也是人发明出来的嘛) 为了解决ArrayList的这一短板 聪明的程序员就使用另一个集合
ArrayList 增删改查的源码
从源码我们可以看出 不管是插入和删除元素的时候 ArrayList都会复制数组操作 这也就导致了它的效率不高
1 //查询元素
2 public E get(int index) {
3 //检查元素是否越界
4 rangeCheck(index);
5
6 return elementData(index);
7 }
8
9
10 //按顺序添加元素
11 public boolean add(E e) {
12 //确认开启扩容机制
13 ensureCapacityInternal(size + 1); // Increments modCount!!
14 elementData[size++] = e;
15 return true;
16 }
17
18 //在指定位置插入元素
19 public void add(int index, E element) {
20 //检查索引是否越界
21 rangeCheckForAdd(index);
22 //确认开启扩容机制
23 ensureCapacityInternal(size + 1); // Increments modCount!!
24 //复制数组
25 System.arraycopy(elementData, index, elementData, index + 1,
26 size - index);
27 //替换元素
28 elementData[index] = element;
29 size++;
30 }
31
32
33
34
35 //移除某个元素
36 public E remove(int index) {
37 rangeCheck(index);
38
39 modCount++;
40 E oldValue = elementData(index);
41
42 int numMoved = size - index - 1;
43 if (numMoved > 0)
//复制数组
44 System.arraycopy(elementData, index+1, elementData, index,
45 numMoved);
46 elementData[--size] = null; // clear to let GC do its work
47
48 return oldValue;
49 }
50
51
52
LinkedList
LinkedList它的底层是双向链表实现的非线程安全的集合,它是一个链表结构,不能像数组一样随机访问,必须是每个元素依次遍历直到找到元素为止。其结构的特殊性导致它查询数据慢。 接下来我们来看看它的结构模型
插入、删除 :因为是链表结构 所以它的插入效率很高 (如果在14 和 18之间插入一个33 的话,链表直接会将连接到18的链子断开 然后连接上33所在的前节点 数据18的前节点再连接上33的后节点 如图2所示) 也就是说 插入一个数字我们只需要将(14 和 18 之间的)链表断开 再将14和33之间的链表连上即可 比ArrayList的数组复制效率高
查询、修改 :LinkedList 查询速度慢 因为它要遍历整个整个集合 直到找到元素为止 如果集合数组多的话 消耗的资源就多 而ArrayList是通过数组下标定位速度快 同样他也是线程不安全的
linkedList
在执行查询时 先判断元素是靠近头部还是尾部 如果是头部 若靠近头部,则从头部开始依次查询判断
执行插入时 判断是插入到中间还是尾部 如果插入到尾部 直接将尾节点的下一个指针指向新增节点。如果插入到中间 获取到当前节点的上一个节点(D) 并将D节点的后指针指向新的节点头指针 然后新增节点的下一个指针指向当前节点。
1 //查询元素
2 public E get(int index) {
3 //检查所引是否越界
4 checkElementIndex(index);
5 return node(index).item;
6 }
7
8 // 返回指定索引处的节点
9 Node<E> node(int index) {
10 // 指定的索引值与链表大小右移一位,及除以 2 进行比较
11 if (index < (size >> 1)) { // 索引小,则从首节点向后扫描,直到索引值处
12 Node<E> x = first;
13 for (int i = 0; i < index; i++)
14 x = x.next;
15 return x;
16 } else { // 索引大,则从尾节点向前扫描,直到索引值处
17 Node<E> x = last;
18 for (int i = size - 1; i > index; i--)
19 x = x.prev;
20 return x;
21 }
22 }
23
24
25 //移除指定元素
26 public E remove(int index) {
27 checkElementIndex(index);
28 return unlink(node(index));
29 }
30
31 //在指定位置添加元素
32 public void add(int index, E element) {
33 //检查所引是否越界
34 checkPositionIndex(index);
35 // 在链表末尾天添加
36 if (index == size)
37 linkLast(element);
38 else
39 linkBefore(element, node(index));
40 }
41
42 private static class Node<E> {
43 E item;
44 //头节点
45 Node<E> next;
46 //尾节点
47 Node<E> prev;
48 Node(Node<E> prev, E element, Node<E> next) {
49 this.item = element;
50 this.next = next;
51 this.prev = prev;
52 }
53 }
54
55 /**
56 * Links e as last element.
57 */
58 void linkLast(E e) {
59 //用l来临时保存未插入前的last节点
60 final Node<E> l = last;
61 //创建一个值为e的新节点 添加第一个元素时 l = null
62 final Node<E> newNode = new Node<>(l, e, null);
63 //将新节点赋值的last
64 last = newNode;
65 if (l == null)
66 first = newNode;
67 else
68 l.next = newNode;
69 size++;
70 modCount++;
71 }
Vector
Vector的数据结构和使用方法 跟ArrayList相同 不同之处在于Vector是线程安全的 几乎所有的对数据操作的方法都被synchronized关键字修饰 synchronized是线程同步的 当一个线程获得Vector对象锁的时候 其它的线程必须等到它执行完毕之后(锁被释放)才能执行
总结
1.ArrayList 它的底层是一个数组 查询修改数据快(通过下标定位) 但是插入删除数据比较慢 (插入数据慢是因为复制数组耗时) 为了改进这个缺点 于是就有了LinkedList数组 它是一个链表结构 插入和删除数据很快(只需要修改指针引用) 但是查询和修改数效率低(他要查询到整个链表从第一个开始寻找 一直找到为止)
2.ArrayList 和LinkedList都是线程不安全的
3.Vector是线程安全的 但是效率低 当我们执行单个线程的时候ArrayList的效率高于Vector
java集合框架使用原理分析的更多相关文章
- Java集合框架源码分析(2)LinkedList
链表(LinkedList) 数组(array)和数组列表(ArrayList)都有一个重大的缺陷: 从数组的中间位置删除一个元素要付出很大的代价,因为数组中在被删除元素之后的所有元素都要向数组的前端 ...
- Java集合:ConcurrentHashMap原理分析
集合是编程中最常用的数据结构.而谈到并发,几乎总是离不开集合这类高级数据结构的支持.比如两个线程需要同时访问一个中间临界区(Queue),比如常会用缓存作为外部文件的副本(HashMap).这篇文章主 ...
- 1.Java集合-HashMap实现原理及源码分析
哈希表(Hash Table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常 ...
- Java集合框架之接口Collection源码分析
本文我们主要学习Java集合框架的根接口Collection,通过本文我们可以进一步了解Collection的属性及提供的方法.在介绍Collection接口之前我们不得不先学习一下Iterable, ...
- 【集合框架】Java集合框架综述
一.前言 现笔者打算做关于Java集合框架的教程,具体是打算分析Java源码,因为平时在写程序的过程中用Java集合特别频繁,但是对于里面一些具体的原理还没有进行很好的梳理,所以拟从源码的角度去熟悉梳 ...
- JAVA常用数据结构及原理分析
JAVA常用数据结构及原理分析 http://www.2cto.com/kf/201506/412305.html 前不久面试官让我说一下怎么理解java数据结构框架,之前也看过部分源码,balaba ...
- java集合框架之java HashMap代码解析
java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...
- 浅入深出之Java集合框架(下)
Java中的集合框架(下) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,哈哈这篇其实也还是基础,惊不惊喜意不意外 ̄▽ ̄ 写文真的好累,懒得写了.. ...
- Java集合框架详解(全)
一.Java集合框架概述 集合可以看作是一种容器,用来存储对象信息.所有集合类都位于java.util包下,但支持多线程的集合类位于java.util.concurrent包下. 数组与集合的区别如下 ...
随机推荐
- Python杂谈: __init__.py的作用
我们经常在python的模块目录中会看到 "__init__.py" 这个文件,那么它到底有什么作用呢? 1. 标识该目录是一个python的模块包(module package ...
- Collection was modified; enumeration operation may not execute.的异常处理
Collection was modified; enumeration operation may not execute.的异常处理 在运行程序时遇到这样一段异常,仔细检查后发现是使用Foreac ...
- Quartz Cron 生成工具
/** * 每周期 */ function everyTime(dom) { var item = $("input[name=v_" + dom.name + "]&q ...
- InfoPath分别定义New/Edit 表单
InforPath自定义表单时,默认是New/Edit是相同的,有时不能满足特殊情况,例如,某些字段在新建时不需填,编辑才改.或者编辑时不能编辑特定字段.这时最方便的方法是分别定义表单,按不同情况使用 ...
- 剖析Qt的事件机制原理(源代码级别)
在用Qt写Gui程序的时候,在main函数里面最后依据都是app.exec();很多书上对这句的解释是,使Qt程序进入消息循环.下面我们就到exec()函数内部,来看一下他的实现原理.Let's go ...
- 基于ASP.NET的新闻管理系统(一)
1. 项目简介 1.1设计内容 (1)可以在首页查看各类新闻,可以点击新闻查看具体内容:可以查看不同类型的新闻,并了解热点新闻,可以在搜索框里输入要查找的内容. (2)在后台界面中,管理员可以修改密码 ...
- 百度AI开放平台,语音识别,语音合成以及短文本相似度
百度AI开放平台:https://ai.baidu.com/ 语音合成 from aip import AipSpeech APP_ID=" #'你的 App ID' API_KEY=&qu ...
- 3012C语言_数据
第二章 数据 2.1 数据类型 2.1.1 数据类型决定 1. 数据占内存字节数 2. 数据取值范围 3. 其上可进行的操作 2.2基本数据类型 2.2.1分类 基本类型 类型 符号 关键字 字节 1 ...
- ES 20 - 查询Elasticsearch中的数据 (基于DSL查询, 包括查询校验match + bool + term)
目录 1 什么是DSL 2 DSL校验 - 定位不合法的查询语句 3 match query的使用 3.1 简单功能示例 3.1.1 查询所有文档 3.1.2 查询满足一定条件的文档 3.1.3 分页 ...
- linux Apache设置https访问以及加载mod_ssl.so模块以及问题解决
开始之前的话: 1.配置好服务器防火墙的443端口规则: 2.购买好证书文件,我是沃通证书,准备好证书,这里不演示证书的购买和安装. 3.根据服务器类型下载文件,apache一共有4个文件 这里提供沃 ...