java基础之集合框架

一、List、Set、Map的区别
(1).从类的继承层次上看List和set都是继承自Collection接口。而Map是自成一体系。
(2).List、set、Map作为Java集合框架,对集合内的元素的存储也是各有特点,List和set是单值存储,map则是以键值对的形式存储。
(3).List按元素放入顺序存储元素,元素是可重复的,而set中元素的位置则是由其hashcode决定的,其位置是固定的,set中存放的元素是不可以重复的。map中key是不可以重复的。
(4).List和set都可通过迭代器直接完成对每个元素的迭代,该迭代器map有两种方式迭代:获得keySet,然后迭代keySet;获得EntrySet对象迭代器,依次迭代该对象。
(5).从底层实现来说,List常用的实现类有ArrrayList和LinkedList,其分别是通过数组和双向链表结构实现,而set则一般是通过其对应的map实现,如HashSet是通过HashMap实现,TreeSet是通过TreeMap实现,map底层则是通过Entry数组实现。

二、关于HashMap、LinkedHashMap、TreeMap、HashTable
HashMap是非常高效的集合框架,其内部实现key做了hash算法,然后将hash值映射到内存地址(即Entry数组下标索引),直接获取key对象的数据,其高效性主要由以下几点保证:
(1).hash算法是高效的;
(2).hash值到内存地址(Entry索引)的算法是快速的;
(3).根据内存地址可以直接去的对应的值;
影响HashMap性能的因素:
(1).hash的冲突。通过追溯其put()方法可得知在map中新增一个元素时,会根据其key的hash值计算出其在entry数组中存储位置,如新增元素key与对应位置key冲突(hash相等且key值相等),则会覆盖已有元素,并将新的元素的next执行旧值。如key不冲突,则直接放到该位置。因此,如果hash算法的重复度会影响hash的性能。
(2).hash的容量参数。因此每次hashmap的扩容都会新建Entry数组,然后遍历原数组将元素添至新数组,因此尽量避免或减少hashMap扩容的次数,可大幅度提高其性能。决定hashMap容量的参数有loadFactor(负载因子,实际存储元素个数与内部数组总大小的比值)和threadold(map容量阈值,超过该值会进行扩容)。
LinkedHashMap:
(1).它继承自HashMap,它具备HashMap高性能的优良特性,并在此基础上,在其内部维护了一个链表,可维护元素的顺序。
(2).实现两种顺序类型:插入顺序和最近访问顺序。通过accessOrder设置切换。
TreeMap:
(1).TreeMap基于红黑树实现,是一种平衡查找树。
(2).TreeMap提供强大的排序功能,通过在map构造时传入基于key排序的实现了Comparator接口的排序类,或对放入元素实现Compareable接口两种方法实现的。而LinkedHashMap与其不同之处在于LinkedHashMap是固定的排序方式,只能按插入顺序或最近访问顺序,而TreeMap排序是可以自定义的。
HashMap与HashTable比较:
(1).HashTable是线程安全的,HashMap不安全。
 (2) .HashTable不允许key或value使用null值,而HashMap可以。
(3).内部算法上它们对key的hash算法和hash值映射到内存索引的算法不同。它们的性能相差无几。

三、关于ArrayList、Vector、LinkedList
ArrayList与Vector比较:
ArrayList与Vector几乎使用了相同的算法,它们底层都是基于数组实现的,唯一区别就是对多线程的支持,ArrayList没有synchronized方法因此是线程不安全的,Vector是线程安全的。因此在理论上,不考虑线程安全的情况下,ArrayList性能要好于Vector,但在实际测试中性能相差无几。
ArrayList与LinkedList比较:
(1).ArrayList基于数组实现,LinkedList基于双向循环列表实现。
(2).元素的添加:由于ArrayList基于数组实现,所以其性能取决于其ensureCapacity()方法,即数组的扩容,扩容会导致对现有元素的复制操作,通过源码可知其数组复制是通过System.arrayCopy()方法实现,因此add()操作效率还相当高。而LinkedList则不存在扩容问题,但每次元素新增都要新建一个Entry对象,并进行诸多赋值操作,在频繁的系统调用中对性能会有一定影响,其对堆内存和GC的要求也相对更高。实际应用中可根据业务需求选择,如需要经常在集合尾端新增元素,可选择ArrayList,而如果是在任意位置新增元素则可选择LinkedList。
(3).元素的删除:同元素的添加,ArrayList元素的移除同样会导致数组重组,这里只给出实际开发过程中的结论,如移除集合头部或靠前位置元素的情况较多,应选择LinkedList,而删除尾部甚至中部以后的元素,选用ArrayList则相对效率更高。
(4).元素的遍历:通过ForEach和迭代器两种方式对元素的循环效率几乎一样,通过对测试代码反编译可知,ForEach就是通过迭代器实现,但由于多了异步赋值操作,故ForEach性能低于迭代器;而对ArrayList进行for循环则效率最高,对LinkedList则性能特别差,特别是元素很多的情况下。

三、关于set
(1).set底层基于map实现,如HashSet基于HashMap实现,set中存放的元素会保存在底层map的key中,LinkedHashSet底层基于LinkedHashMap实现;TreeSet底层基于TreeMap实现,所以各自特定可依据其对应map推敲而来。
(2).个set实现的排序:HashSet输出无序、LinkedHashSet按插入顺序输出、TreeSet和TreeMap一样,可通过Comapreable或Comparator的方法自定义排序。

四、集合类一般不建议在迭代模式下去修改或删除集合中的元素,会抛出异常。

五、集合优化:
除上述集合选择优化外,集合使用时,通常有以下几种优化原则:
(1).分离循环中反复使用的代码:如for(int i = 0; i < list.size();i++)中的list.size()的调用,可在循环前定义变量获得list大小。
(2).省略相同的操作:如经常在代码中会获取当前循环出的元素的各种属性,建议先定义临时变量获得当前元素,而不是没事list.get(i).get...();
(3).尽量减少循环内部方法调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值