几种集合的实现起来用的数据结构

哈希表:

  哈希表底层,使用的也是数组机制数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,当需要把这些对象给数组中存放时,那么会根据这些对象的特有数据结合相应的算法,计算出这个对象在数组中的位置,然后把这个对象存放在数组中。而这样的数组就称为哈希数组,即就是哈希表。

HashMap就是一个插入慢、查询快的数据结构。

HashMap:数组+链表

HashSet:底层就是hashMap,实际也是:数组+链表

TreeMap:红黑树

TreeSet: 底层就是 TreeMap,实际也是:红黑树

SortedSet:底层是TreeSet,实际也是:红黑树

LinkedList:底层是一个双向链表

*******************************【红黑树和平衡二叉树的比较】***************************************************************

RB-Tree和AVL树作为BBST,其实现的算法时间复杂度相同,AVL作为最先提出的BBST,貌似RB-tree实现的功能都可以用AVL树是代替,那么为什么还需要引入RB-Tree呢?

  1. 红黑树不追求"完全平衡",即不像AVL那样要求节点的 |balFact| <= 1,它只要求部分达到平衡,但是提出了为节点增加颜色,红黑是用非严格的平衡来换取增删节点时候旋转次数的降低,任何不平衡都会在三次旋转之内解决,而AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多。
  2. 就插入节点导致树失衡的情况,AVL和RB-Tree都是最多两次树旋转来实现复衡rebalance,旋转的量级是O(1)
    删除节点导致失衡,AVL需要维护从被删除节点到根节点root这条路径上所有节点的平衡,旋转的量级为O(logN),而RB-Tree最多只需要旋转3次实现复衡,只需O(1),所以说RB-Tree删除节点的rebalance的效率更高,开销更小!
  3. AVL的结构相较于RB-Tree更为平衡,插入和删除引起失衡,如2所述,RB-Tree复衡效率更高;当然,由于AVL高度平衡,因此AVL的Search效率更高啦。
  4. 针对插入和删除节点导致失衡后的rebalance操作,红黑树能够提供一个比较"便宜"的解决方案,降低开销,是对search,insert ,以及delete效率的折衷,总体来说,RB-Tree的统计性能高于AVL.
  5. 故引入RB-Tree是功能、性能、空间开销的折中结果。
    5.1 AVL更平衡,结构上更加直观,时间效能针对读取而言更高;维护稍慢,空间开销较大。
    5.2 红黑树,读取略逊于AVL,维护强于AVL,空间开销与AVL类似,内容极多时略优于AVL,维护优于AVL。
    基本上主要的几种平衡树看来,红黑树有着良好的稳定性和完整的功能,性能表现也很不错,综合实力强,在诸如STL的场景中需要稳定表现。

红黑树的查询性能略微逊色于AVL树,因为其比AVL树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的AVL树最多多一次比较,但是,红黑树在插入和删除上优于AVL树,AVL树每次插入删除会进行大量的平衡度计算,而红黑树为了维持红黑性质所做的红黑变换和旋转的开销,相较于AVL树为了维持平衡的开销要小得多

HashSet 

hashset集合采用hash算法来决定元素的存储位置不同,TreeSet采用红黑数的数据结构来存储集合元素,那么TreeSet的两种排序方法:自然排序和定制排序。默认情况下才用自然排序(按照升序排列);

1、不能保证元素的排序顺序,顺序可能与添加顺序不同,顺序也有可能发生变化;

2、HashSet不是同步的,如果多个线程同时访问一个HashSet,假设有两个或者两个以上线程同时修改了HashSet集合时,则必须通过代码来保证其同步;

3、集合元素值可以是NULL,键不能为NULL;

TreeSet

        HashSet和TreeSet是Set的两个典型实现,到底如何选择HashSet和TreeSet呢?HashSet的性能总是比TreeSet好(特别是常用的添加、查询元素操作),因为TreeSet需要额外的的红黑书算法来维护集合元素的次序。只有当需要一个保持排序的Set时,才应该使用TreeSet,否则都应该使用HashSet。

        HashSet还有一个子类:LinkedHashSet,对于普通的插入、删除操作,LinkedHashSet比HashSet要略微慢一点,这是由维护链表所带来的额外开销造成的,但由于有了链表, 遍历LinkedHashSet会更快。

        EnumSet是所有Set实现类中性能最好的,但他只能保存同一个枚举的枚举值作为集合元素。

必须指出的是Set三个实现类HashSet、TreeSet、EnumSet都是线程不安全的。如果有多个线程同时访问一个Set集合,并且超过一个线程修改了该Set集合,则必须手动保持该Set集合的同步性,通过可以通过Collections工具类的synchronizedSortedSet方法来包装该Set集合。此操作最好在创建时进行,以防止对Set集合的意外非同步访问。例如:

Collection c=Collections.synchronizedCollection(new ArrayList());

EnumSet

EnumSet是一个专为枚举类型设计的集合类,EnumSet中的所有元素都必须是指定的枚举类型的枚举值,该枚举类型在创建EnumSet时显示或隐式地指定。EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的顺序。

EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑、高效,因此EnumSet对象占用的内存很小,而且运行效率很好。尤其是进行批量操作时如果其参数也EnumSet集合,则批量操作的执行速度也非常快。

EnumSet集合不允许加入null元素,如果试图插入null元素,EnumSet将抛出NullPointerException异常,如果只是想判断EnumSet是否包含null元素或者试图删除null元素都不会抛出异常,只是删除操作将返回false,因为没有任何null元素被删除。

EnumSet es1=EnumSet.allof(Season.class);

List集合

List集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问制定位置的集合元素。List集合默认按元素的添加顺序设置元素的索引,例如第一次添加元素的索引为0,第二次添加元素的索引为1.。。。;

List作为Collection接口的子接口,当然可以使用Collection接口里的全部方法,而且由于List是有序集合,因此List集合里增加了一些根据索引来操作集合元素的方法。

ArrayList和Vector实现类

ArrayList和Vector作为List类的两个典型实现,完全支持前面介绍的List接口的全部功能;

ArrayList和Vector类都是基于数组实现的List类,所以ArrayList和Vector类封装了一个动态的、允许再分配ideaObject[]数组。ArrayList或Vector对象使用initalCapacity参数来设置该数组的长度,当向ArrayList或Vector中添加元素超出了该数组的长度时,他们的initalCapacity会自动增加。

ArrayList和Vector的显著区别是:ArrayList是线程不安全的,当多个线程访问同一个集合时,如果有超过一个线程修改了ArrayList集合,则程序必须手动保证该集合的同步性;但Vector集合是线程安全的,无须程序保证集合的同步性,因为Vector是线程安全的,所以Vector性能比ArrayList的性能要低,实际上,即使需要保证List集合线程安全,也同样不推荐使用Vector实现类,后面会介绍一个Collectioins工具类,他可以将一个ArrayList变成线程安全的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值