小言_互联网的博客

学习笔记:突出程序员基本功(三)常见java集合的实现细节

485人阅读  评论(0)

1.Set和Map

set代表一种集合元素无序,集合元素不可重复的集合,Map则代表一种由多个key-value对组成的集合。可以说,map集合是set集合的扩展。map所有key集中起来就是个set集合,而对于map而言,相当于每个元素都是key-value的set集合。

1.1 set和map的关系

 

1.2 HashMap和HashSet

虽然集合号称存储的是java对象,但实际上并不会真正将java对象放入set集合中,而只是在set集合中保留这些对象的而引用而言。也就是说,java集合实际上是多个引用变量所组成的集合,这些引用变量指向实际的java对象。
HashMap在底层将key=value当成一个整体进行处理,这个整体就是一个Entry对象。HashMap底层采用要给Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据Hash算法来决定其存储位置;当需要取出一个Entry时,也会根据Hash算法找到其存储位置,直接去除该Entry。

HashSet封装了要给HashMap对象来存储所有的集合元素。所有放入HashSet中的集合元素实际上由HashMap的key来保存,而HashMap的value则存储了一个PRESENT,它时要给静态的Object对象。

1.3 TreeMap和TreeSet

TreeSet底层采用了一个NavigableMap来保存TreeSet集合的元素。但实际上,由于NavigableMap只是一个接口,因此底层依然是使用TreeMap来包含Set集合中的元素。与HashSet类似,TreeSet里绝大部分方法都是直接调用TreeMap的方法来实现的。

对于TreeMap而言,它采用一种被称为“红黑树”的排序二叉树来保存Map中每一个Entry(每一个Entry都被当成“红黑树”)的一个节点对待。也意味着TreeMap添加元素,取出元素的性能都比HashMap低。当TreeMap添加元素时,需要通过循环找到新增Entry的插入位置,因此比较消耗性能;当从TreeMap中取出元素时,需要通过循环才能找到合适的Entry,也比较消耗性能。但TreeMap,TreeSet相比HashMap,HashSet的优势在于:TreeMap中的所有Entry总时按key根据指定排序规则保持有序状态,TreeSet中的所有元素总是根据指定排序规则保持有序状态。

TreeMap.put(k,v); 每当程序希望添加新节点时,总是从树的根节点开始比较,即将跟节点当成当前节点。如果新增节点大于当前节点而且当前节点的右子节点存在,则以右子节点作为当前节点;如果新增节点小于当前节点而且当前节点的左子节点存在,则以左子节点作为当前节点;如果新增节点等于当前节点,则用新增节点覆盖当前节点,并结束循环--知道找到某个节点的左,右子系欸但不存在,将新节点添加为该节点的子节点。如果新节点比该节点大,则添加为右子节点;如果新节点比该节点小,则添加为左子节点。

2. Map和List

不管是HashMap,还是TreeMap,它们的values()方法都可返回其所有value组成的Collection集合;通常理解这个Collection集合因该是一个List集合,因为Map的多个value允许重复。但实际上,HashMap,TreeMap的values()方法的实现要更巧妙。这两个Map对象values()方法返回的是要给不存储元素的Collection集合,当程序遍历Collection集合时,实际上就是遍历Map对象的value。

map和list底层实现上并没有太大的相似之处,只是在用法上存在一些相似处:即可以说list相当于所有key都是int类型的map,也可以说map相当于索引时任意类型的list。

3.ArrayList和LinkedList

在list集合的实现类中,主要右3个实现类:ArrayList,Vector,LinkedList

Vector和ArrayList这两个集合类的本质并没有太大的不同,它们都是实现了list接口,而且底层都是基于java数组来存储集合元素。ArrayList使用了transient修饰了elementData数组,故从序列化机制的角度来看,ArrayList的实现比Vector的实现更安全。但是Vector的方法增加了synchronized修饰,而且两者绝大部分方法的实现是相同的,故可以理解为vector其实就是ArrayList的线程安全版本。

List代表一种线性表的数据结构,ArrayList则是一种顺序存储的线性表。ArrayList底层采用数组来保存每个集合元素,LinkedList则是一种链式存储的线性表。其本质上就是一个双向链表,但是它不仅实现了List接口,还实现了Deque接口。也就是说LinkedList即可以当成双向链表使用,也可以当成队列使用,还可以当成栈来使用(Deque代表双端对垒,即具有队列的特征,也具有栈的特征)

获取元素ArrayList性能比LinkedList要好,而添加元素ArrayList性能要比LinkedList差。

4. Iterator迭代器

Iterator是一个迭代器接口,它专门用于迭代各种Collection集合,包括set结婚和lset集合。

java要求各种集合都要提供一个iterator()方法,该方法返回一个Iterator用于遍历该集合中元素,至于返回的Iterator到底是哪种实现类,程序并不关心,这就是典型的“迭代器模式”。

 

 

 

 

 

 


转载:https://blog.csdn.net/java_shm/article/details/101213312
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场