Java中List,Map的学习以及使用。底层原理的剖析

 

List集合

List集合在编辑语言中是类库中的一个类,它继承与conllection,是一个接口的存在,不能实例化,需要实例化一个ArrayListlinkedlist,通俗点就是一张表、目录清单的。在集合中的任意位置进行增删改查操作都很快,但是不支持随机的获取数据。还可以通过泛型进行多种类型的数据存储,其中包括自己定义的类型。

List接口存储是一组不唯一的,有序的对象 其中元素是可以重复的 有索引,可以很快的进行检索

List有两个接口:ArrayList Linkedlist

ArrayList 是底层的数据结构,使用的数组结构

特点:查询的速度快,但是增删改慢,线程不同步

Linkedlist 使用的是链表数据结构

特点:增删快,但是查询速度慢

 

List array 的区别

相同点:

都可以表示一组同类型的对象

都使用下标进行搜索

不同点:

数组可以储存任何数据类型元素

List不能存储基本的数据类型,必须要经过包装

数组容量是固定的 list 是可以随数据的变化而变化

数组效率高 list要维护额外的内容,所有效率相对来说比较低点

在选择使用是:

如果容量固定,优先使用数组,存储的数据类型更多,更高效

如果容量不能固定,就选择list比较好点

 

ArrayList实现原理

ArrayList是List接口的可变数组非同步实现,并允许包括null在内的所有元素。

底层使用数组实现

该集合是可变长度数组,数组扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量增长大约是其容量的1.5倍,这种操作的代价很高。

采用了Fail-Fast机制,面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险

remove方法会让下标到数组末尾的元素向前移动一个单位,并把最后一位的值置空,方便GC

 

Linkedlist实现原理

LinkedList是List接口的双向链表非同步实现,并允许包括null在内的所有元素。

底层的数据结构是基于双向链表的,该数据结构我们称为节点

双向链表节点对应的类Node的实例,Node中包含成员变量:prev,next,item。其中,prev是该节点的上一个节点,next是该节点的下一个节点,item是该节点所包含的值。

它的查找是分两半查找,先判断index是在链表的哪一半,然后再去对应区域查找,这样最多只要遍历链表的一半节点即可找到

 

ListIterator  

Iterator的子接口,提供了专门操作List的方法   

Contains

list中是否包含某个元素

ArrayList和LinkedList区别

A是基于动态的数组的数据结构  L 是基于链表的数据结构

例子:准备一个为2000的数组,第一个为a0 最后一个为a1999

A 实施添加/删除的操作时:(数组)

   

如果只是单纯的往最后一个添加/删除数据,他就只会影响这个数组的长度,其他的什么都不会影响,这个添加操作是很快的;如果要在数据的a100处(前面或者后面)添加/删除数据时,当前数据后面的每个数据的下标值都会改变,数组小的还无所谓,那数组很庞大呢,后面都会有所影响,那样的话就很浪费时间了。

 

L 实施添加/删除操作:(双向循环链表)

        

   因为L的存储是以链表方式进行存储的,也是随机的,所以他们不存在A中的下标数,只有上一项或者是下一项;所以L在做添加或者删除操作时,对链表中的数据不会有太大的影响(因为L中的数据之间没有关联、没有什么连续性可言)。所以L的添加/删除比A的要快。

 

 

实施查看操作时:

  

因为A的数据结构是数组结构,它存在下标数,如图(左),定义一个int的数组aa12000a2=2004a3=2008.......an=?当要查询其中的某个数据时,可以通过直接计算这个数据的下标值就可以直接获取到该值,省时省力。

L 的数据结构是链表结构,他里面的数据没有任何的关联,随机的,当他在实施查看他会从头开始检索,当检索到你要所要的数据时,他才会停止;当你数据少了还好点,那当你有几百万的数据时,就费事费力。所以对于查询方面来说,LA占优势。

 

 

 

 

Map(键值对)

Map也是集合的一种,主要是通过键值对的方式进行存储,其中值是可以重复的,键必须是唯一的,也可以是null,但只能有一个是空,键值存在单向的一对一关系,可以通过制定的键找到唯一的,确定的值。

Map主要的实现类有hashMap hashTable linkedHashMap TerrMap

键就是你要存储数据的编号   值就是你要储存的数据

HashMap

保存数据是先进后出。无序。查询速度比较快,不支持线程同步,但支持多个线程同时写hashmap,但是也存在不好的地方,会导致数据不一致,需要同步的话,可以使用Collection的synchronizedMap方法使其同步

HashMap是一个散列集合,其底层是数组+链表结构,主体部分是个长度很长的数组

 

主体 : Entry数组(实际存key,value的对象); 
链表 : 通过next方法指向链表下一个结点

 

实现原理:

HashMap是基于哈希表的Map接口的非同步实现,允许使用null值和null键,但不保证映射的顺序。

底层使用数组实现,数组中每一项是个单向链表,即数组和链表的结合体;当链表长度大于一定阈值时,链表转换为红黑树,这样减少链表查询时间。

HashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Node对象。HashMap底层采用一个Node[]数组来保存所有的key-value对,当需要存储一个Node对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Node时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Node。

HashMap进行数组扩容需要重新计算扩容后每个元素在数组中的位置,很耗性能

采用了Fail-Fast机制,通过一个modCount值记录修改次数,对HashMap内容的修改都将增加这个值。迭代器初始化过程中会将这个值赋给迭代器的expectedModCount,在迭代过程中,判断modCount跟expectedModCount是否相等,如果不相等就表示已经有其他线程修改了Map,马上抛出异常

 

fail-fast 机制是java集合(Collection)中的一种错误机制。(不是太理解)

 

hashMap是根据键hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。

 

hashCodejdk根据对象的地址或者字符串或者数字算出来的int类型的数值,对象通过调用hashCode()方法返回该对象的哈希码值。支持此方法是为了提高哈希表的性能。

 

HashTable

Hashtable底层实现是通过开链法来实现的,hash table表格内的元素称为桶(bucket),而由桶所链接的元素称为节点(node),其中存入桶元素的容器为stl本身很重要的一种序列式容器——vector容器。之所以选择vector为存放桶元素的基础容器,主要是因为vector容器本身具有动态扩容能力,无需人工干预。

hashTable是Dictionary的子类,它的线程是同步的,在多线程的操作下,他不用专门的操作就可以安全的使用hashTable,hashTable是不允许有空值的,不用管是键还是值,都不能为null

 

有两个参数影响其性能:初始容量和加载因子。

容量:哈希表中桶的容量。 (哈希表创建时的容量)

加载因子对哈希表在其容量自动增加之前可以达到多满的一个尺度。

 

LinkedhashMap

     

他是双向链表结构的,保存了元素的插入顺序,Iterator遍历元素时按照插入的顺序排列,支持线程同步LinkedhashMap是hashMap的子类,他拥有hashMap的所有的特性。

 

L是有序的,L增加了两个属性来保证顺序:双向链表的头结点header和标志位accessOrder。Header是L所维护的双向链表的头结点;accessOrder标志位为true时,表示双向链表中的元素按照访问的先后顺序排列,可以看到,虽然Entry插入链表的顺序依然是按照其put到LinkedHashMap中的顺序,但put和get方法均有调用recordAccess方法(put方法在key相同时会调用)。recordAccess方法判断accessOrder是否为true,如果是,则将当前访问的Entry(put进来的Entry或get出来的Entry)移到双向链表的尾部(key不相同时,put新Entry时,会调用addEntry,它会调用createEntry,该方法同样将新插入的元素放入到双向链表的尾部,既符合插入的先后顺序,又符合访问的先后顺序,因为这时该Entry也被访问了);当标志位accessOrder的值为false时,表示双向链表中的元素按照Entry插入LinkedHashMap到中的先后顺序排序,即每次put到LinkedHashMap中的Entry都放在双向链表的尾部,这样遍历双向链表时,Entry的输出顺序便和插入的顺序一致,这也是默认的双向链表的存储顺序。因此,当标志位accessOrder的值为false时,虽然也会调用recordAccess方法,但不做任何操作。

http://blog.csdn.net/justloveyou_/article/details/71713781

linkedHashMap详解网站

   

实现原理:

LinkedHashMap继承于HashMap,底层使用哈希表和双向链表来保存所有元素,并且它是非同步,允许使用null值和null键。

基本操作与父类HashMap相似,通过重写HashMap相关方法,重新定义了数组中保存的元素Entry,来实现自己的链接列表特性。该Entry除了保存当前对象的引用外,还保存了其上一个元素before和下一个元素after的引用,从而构成了双向链接列表。

 

TreeMap

底层是二叉树数据结构,线程不同步,可用于给map集合中的键进行排序,T中所有的数据元素都保持着某种固定的顺序。

Treemap:适用于按自然顺序或自定义顺序遍历键(key)

特点:保存元素key-value不能为null,允许key-value重复;遍历元素时随机排列。

T的实现是红黑树算法的实现,

http://blog.csdn.net/zhangyuan19880606/article/details/51234420

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值