java常见数据结构整理
java中容器类数据结构主要在java.util包中。
java.util包中三个重要的接口及特点:List(列表)、Set(保证集合中元素唯一)、Map(维护多个key-value键值对,保证key唯一)。其不同子类的实现各有差异,如是否同步(线程安全)、是否有序。
常用类继承树:
以下结合源码讲解常用类实现原理及相互之间的差异。
Collection (所有集合类的接口)
List、Set都继承自Collection接口,查看JDK API,操作集合常用的方法大部分在该接口中定义了。
Collections (操作集合的工具类)
对于集合类的操作不得不提到工具类Collections,它提供了许多方便的方法,如求两个集合的差集、并集、拷贝、排序等等。
由于大部分的集合接口实现类都是不同步的,可以使用Collections.synchronized*方法创建同步的集合类对象。
如创建一个同步的List:List synList = Collections.synchronizedList(new ArrayList());
其实现原理就是重新封装new出来的对象,操作对象时用关键字synchronized同步。看源码很容易理解。
Collections部分源码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<code class="language-java hljs ">//Collections.synchronizedList返回的是静态类SynchronizedCollection的实例,最终将new出来的ArrayList对象赋值给了Collection<e> c。static class SynchronizedCollection<e> implements Collection<e>, Serializable { final Collection<e> c; // Backing Collection final Object mutex; // Object on which to synchronize SynchronizedCollection(Collection<e> c) { if (c==null) throw new NullPointerException(); this.c = c; mutex = this; } //... public boolean add(E e) { //操作集合时简单调用原本的ArrayList对象,只是做了同步 synchronized (mutex) {return c.add(e);} } //...}</e></e></e></e></e></code> |
List (列表)
ArrayList、Vector是线性表,使用Object数组作为容器去存储数据的,添加了很多方法维护这个数组,使其容量可以动态增长,极大地提升了开发效率。它们明显的区别是ArrayList是非同步的,Vector是同步的。不用考虑多线程时应使用ArrayList来提升效率。
ArrayList、Vector 部分源码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<code class="language-java hljs ">//ArrayList.addpublic boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! //可以看出添加的对象放到elementData数组中去了 elementData[size++] = e; return true;}//ArrayList.removepublic E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) //移除元素时数组产生的空位由System.arraycopy方法将其后的所有元素往前移一位,System.arraycopy调用虚拟机提供的本地方法来提升效率 System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue;}//Vector add方法上多了synchronized关键字public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true;}</code> |
LinkedList是链表,略懂数据结构就知道其实现原理了。链表随机位置插入、删除数据时比线性表快,遍历比线性表慢。
双向链表原理图:
LinkedList部分源码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<code class="language-java hljs ">//源码很清晰地表达了原理图public class LinkedList<e>extends AbstractSequentialList<e>implements List<e>, Deque<e>, Cloneable, java.io.Serializable{ //头尾节点 transient Node<e> first; transient Node<e> last;}//节点类 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; }}</e></e></e></e></e></e></e></e></e></e></e></code> |
由此可根据实际情况来选择使用ArrayList(非同步、非频繁删除时选择)、Vector(需同步时选择)、LinkedList(频繁在任意位置插入、删除时选择)。
Map(存储键值对,key唯一)
HashMap结构的实现原理是将put进来的key-value封装成一个Entry对象存储到一个Entry数组中,位置(数组下标)由key的哈希值与数组长度计算而来。如果数组当前下标已有值,则将数组当前下标的值指向新添加的Entry对象。
有点晕,看图吧:
完图再看源码,非常清晰,都不需要注释。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<code class="language-java hljs ">public class HashMap<k,v>extends AbstractMap<k,v>implements Map<k,v>, Cloneable, Serializable{ transient Entry<k,v>[] table; public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); //遍历当前下标的Entry对象链,如果key已存在则替换 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))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } addEntry(hash, key, value, i); return null; }}static class Entry<k,v> implements Map.Entry<k,v> { final K key; V value; Entry<k,v> next; int hash;}</k,v></k,v></k,v></k,v></k,v></k,v></k,v></k,v></code> |
TreeMap是由Entry对象为节点组成的一颗红黑树,put到TreeMap的数据默认按key的自然顺序排序,new TreeMap时传入Comparator自定义排序。红黑树网上很多资料,我讲不清,这里就不介绍了。
Set(保证容器内元素唯一性)
之所以先讲Map是因为Set结构其实就是维护一个Map来存储数据的,利用Map结构key值唯一性。
HashSet部分源码:
|
1
2
3
4
5
6
7
8
9
10
11
|
<code class="language-java hljs ">public class HashSet<e>extends AbstractSet<e>implements Set<e>, Cloneable, java.io.Serializable{ //无意义对象来作为Map的value private static final Object PRESENT = new Object(); public boolean add(E e) { return map.put(e, PRESENT)==null; }}</e></e></e></code> |
HashSet、TreeSet分别默认维护一个HashMap、TreeMap。
java常见数据结构整理的更多相关文章
- 转 Python常见数据结构整理
http://www.cnblogs.com/jeffwongishandsome/archive/2012/08/05/2623660.html Python常见数据结构整理 Python中常见的数 ...
- Java常见Exception整理
前言: 技术开发入坑近1年,摸打滚爬,各种升级打怪.因目前从事Java相关,故整理了一下并把常见的异常(Exception)贴出来,一来为了后续提醒自己,二来供即将入坑的朋友打一下预防针!A级(代码逻 ...
- Python常见数据结构整理
Python中常见的数据结构可以统称为容器(container).序列(如列表和元组).映射(如字典)以及集合(set)是三类主要的容器. 一.序列(列表.元组和字符串) 序列中的每个元素都有自己的编 ...
- Java常见运算符整理
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/44724267 本文主要介绍Java中常见的运算符,重点介绍 ...
- Java常见数据结构
HashMap深入浅出 HashMap数据结构 HashMap的本质就是一个数组加链表,数组默认长度是16,存储的元素达到总长度的75%就会扩容一倍.map.put(key,val),实际上就是根据h ...
- Java 常见BUG 整理
1.BigDecimal初始化double 2.Integer java对于-128到127之间的数,会进行缓存,这个范围的Integer对象是同一个! == 是ok,但是超出这个范围就不可以用 ...
- java常见数据结构举例
1. ArrayList(参考) import java.util.*; public class Test{ public static void main(String [] args){ Arr ...
- Java常见错误整理(一)
1.配置完Java环境变量之后,仍然不能使用java命令. 解决方法: 如果是Windows10系统出现此问题,是因为个别Windows10系统不识别“JAVA_HOME”环境变量,将path中所有的 ...
- java 常见数据结构
1)tree 2) queue 3) list 4) stack 5) heap 6) map
随机推荐
- DevExpress ChartControl控件实现图表【转】
1.饼状图图 1.1添加ChartControl控件 在工具箱中找到ChartControl控件,拖到窗口中,创建Pie: 1.2准备数据 private DataTable CreateChartD ...
- IIS7.5配置Gzip压缩解决方案(转)
开启配置HTTP压缩(GZip) 在IIS7中配置Gzip压缩相比IIS6来说实在容易了许多,而且默认情况下就是启用GZip压缩的.如果没有,则可以再功能视图下找到“压缩”项,进入之后就会看到“静态内 ...
- 图形报表 webChart.dll 以及其它的图形报表控件 (转)
http://www.carlosag.net/Tools/WebChart/sampleDataSet.aspx http://www.carlosag.net/Tools/WebChart/sam ...
- 随机蕨(Random Fern)
最近在做 Zdenek Kalal 的 TLD 算法,其成果发表在CVPR 2010 上,文章的名字叫做 P-N Learning: Bootstrapping Binary Classifiers ...
- Laravel validate 500异常 添加手机验证,中文验证与Validator验证的“半个”生命周期
今天来讲一下,Lumen的Validator函数 1 2 3 4 5 6 7 8 9 10 11 use Validator; ... Class .. { public function ...
- hdu 3665Seaside(简单floyd)
Seaside Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- 求通俗讲解下tensorflow的embedding_lookup接口的意思
https://www.zhihu.com/question/48107602 作者:王凯链接:https://www.zhihu.com/question/48107602/answer/15980 ...
- Axure-Axure RP For Chrome 演示扩展
Axure RP生成的Html原型,其中包含JS文件,在本地进行演示时浏览器IE会弹出安全提醒.谷歌浏览器Chrome则需要在线安装一个Axure的扩展工具才可以演示. Axure RP Extens ...
- Linq-Contains查询
customers.Where(c => c.Name.Contains("john"));
- linux kernel系列四:嵌入式系统中的文件系统以及MTD
本节介绍File System和MTD技术 一 FS 熟知的FS有ext2,3,4.但是这些都是针对磁盘设备的.而ES中一般的存储设备为Flash,由于Flash的特殊性: Flash存储按照Bloc ...