java集合框架详解

首先,我想先给一张集合的整体框架图,这张图并不是最详细的图,只是列出比较常见的接口和使用的类

1. Collection接口是集合的根接口,Java中没有提供这个这个接口的直接实现类,但是却让其继承产生了两个接口,就是Set和List;Set中不能包含重复元素且是无序的,List中元素可以重复且有序

2. Map是java.util包中的另一个接口,他和Collection没有关系,是相互独立的,但是都是属于集合的一部分,Map包含了Key-Value的键值对,Map不能包含相同的key,可以有相同的value

3. Iterator所有的集合类都实现了Iterator接口,只是用于遍历集合中元素的接口,主要包含以下三个方法:

        hasNext() 判断是否还有下一个元素

        next() 返回下一个元素

        remove() 删除刚刚next方法返回的元素

4. List:存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引有关的方法,查询速度快,插入或删除数据时慢,因为要移动被修改元素后面的所有元素

5. Set:存放的对象是无序的,同时不能重复

6. Map:以键值对形式存储,键唯一,值不唯一,根据键可以得到值,对map集合遍历是先得到键的set集合,对set集合进行遍历,得到相应的值。

7. 在集合中常见的三种遍历输出方式

     Iterator:迭代输出,是使用最多的输出方式

     foreach:JDK1.5之后提供的新功能,可以输出数组或集合

     for循环

     ListIterator:是Iterator的子接口,专门用于输出List中的内容,功能比Iterator更强大

   代码形式:

     for形式: for(int i=0;i<arr.size();i++){...}

     foreach形式:for(String str:listString){...}

     Iterator形式:Iterator iterator = list.iterator(); while(iterator.hasNext()) { iterator.next()};

8. ArrayList:底层用对象数组实现,非线程安全,查询快,增删慢,扩容机制(当前容量*3)/2+1 ,也就是增加当前容量的50%,如果知道大约需要使用的容量,请在初始化时是就给定容量,避免扩容,影响性能

9. LinkArrayList:底层使用双向链表实现,非线程安全,查询慢,基于链表实现,只能通过顺序访问,但增删快,只需要改变四个指针的指向,不需要移动其他元素

10. Vector:底层使用对象数组实现,线程安全,所有方法都是同步方法,所以效率低,不建议使用,如果在多线程下,有需要同步,可以使用Collections的同步方法对ArrayList进行同步即可

11. Vector和ArrayList的区别:

     相同点:底层都是使用对象数组实现的,都是有序且可以重复

     不同点:Vector是线程安全的,ArrayList是非线程安全的;在进行扩容的时候,Vector是直接(当前容量*2)翻倍,而ArrayList是(当前容量*3)/2+1 ,也就是增加当前容量的50%;ArrayList的效率比Vector要高

12. ArrayList和LinkArrayList的区别

   相同点:都是有序且可以重复,都是非线程安全

   不同点:ArrayList底层使用对象数组实现,LinkArrayList底层使用双向链表实现;ArrayList查询快,增删慢,LinkArrayList查询慢,增删快;ArrayList比LinkArrayList节省内存,LinkArrayList需要保存前后一个元素的指针

13. Array和ArrayList的区别?什么时候更适合使用Array

    Array可以容纳基本数据类型和对象,但ArrayList只能是对象,如果对ArrayList使用基本数据类型,不会报错,因为JDK1.5之后引入自动装箱和拆箱机制,但是这样会影响性能。在大小固定的情况下,可以使用Array

14. HashSet:底层是HashMap实现,特点是存入值不能重复,无序,非线程安全

15. LinkHashSet: 底层使用LinkHashMap实现,特点是能够记录插入顺序,值不能重复,无序,非线程安全

16. TreeSet:底层是TreeMap实现,使用二叉排序树实现,非线程安全

17. HashMap:底层通过对象数组+链表实现,使用key值进行hash算法得到底层数组的下标,然后返回数组对象,所以key值是不可以重复的,HashSet就是利用这个特点实现,只用map的key而不用value,非线程安全(允许一个键为null,多个值为null),默认容量为16,而且每一次扩容都是2的幂次方

18. LinkHashMap: 这个类是HsahMap的子类,特点就是能够记录插入顺序,非线程安全。

19. HashTable:线程安全,不允许键或值为null,是HashMap的线程安全版,它支持线程同步,即任意时刻只有一个线程能写Hashtable,因此也导致了Hashtable在写入的时候比较慢,它继承自Dictionary类

20. TreeMap:底层使用二叉排序树实现,TreeMap实现SortMap接口,能够吧它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,用Iterator遍历TreeMap时,得到的记录是排序过的

21. ConcurrentHashMap:线程安全,并且锁分离,ConcurrentHashMap内部使用段Segment来表示不同的部分,每个Segment其实就是一个小的Hashtable,他们有自己的锁,只要多个修改操作发生在不同的锁上,他们就可以并发进行

22. Map的遍历

      KeySet方式:将Map中所有的键存入到set集合中,因为set具备迭代器,所以可以用迭代方式取出所有的键,再根据get方法,获取每一个键对应的值,keySet()迭代后只能通过get()取key,取到的结果会乱序。

       Set   set = map.keySet();

       Iterator iterator = set.Interator();

       while(iterator.hasNext())

      {

          Object key = iterator.next();

           Object value = map.get(key);

      }

      entrySet方式:Set<Map.Entry<K,V> entrySet() // 返回此映射中包含映射关系的set视图,(一个关系就是一个键值对),就是把(key-value)作为一个整体一对一对存放到set集合中,Map.Entry表示映射关系。entrySet():迭代后,可以e.getKey(), e.getValue()  两种方法来取key和value,返回的是Entry接口

       Set   set = map.entrySet();

       Iterator iterator = set.Interator();

       while(iterator.hasNext())

      {

          Entry e = (Entry) iterator.next();

      }

   推荐使用第二种方式,效率比较高,第一种方式其实是遍历了两次,一次是转为Iterator,一次就是haspMap中取出key所对于的value,而entrySet只是遍历了一遍,它把key和value都放到了entry中,所以快了

23.  HashMap的扩容机制

      HashMap中有 容量(默认16)、负载因子(默认0.75),HashMap并不是等存满了再进行扩容的,它是当前存储容量大于阀值的时候进行扩容,阀值= 容量*负载因子 ,扩容是非常消耗性能的,所以如果在知道大约需要的容量下,建议使用初始化容量方法创建对象,避免扩容的发生,提供程序性能;

24. 为什么容量总是2的n次幂方?

     当数组长度为2的n次幂的时候,hash函数不同的key算得得index相同的几率较小,那么数据在数组上分布就比较均匀,也就是说碰撞的几率小,相对的,查询的时候就不用遍历某个位置上的链表,这样查询效率也就较高了。
      说到这里,我们再回头看一下hashmap中默认的数组大小是多少,查看源代码可以得知是16,为什么是16,而不是15,也不是20呢,看到上面的解释之后我们就清楚了吧,显然是因为16是2的整数次幂的原因,在小数据量的情况下16比15和20更能减少key之间的碰撞,而加快查询的效率。就算不指定的话,也会以大于且最接近指定值大小的2次幂来初始化的

25. HaspMap与TreeMap

     HashMap 通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用Treemap(HashMap中元素的排列顺序是不固定的);在Map中插入,删除和定位元素,HashMap是最好的选择,但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好,是用HashMap要求添加的键类明确定义了HashCode方法和equals方法的实现

26. HashMap和HashTable

      同步性:Hashtable是线程安全的,也就是同步的,而hashMap是线程不安全的,不同步的;

      HashMap允许存在一个为null的键,和多个为null的值

      HashTable不允许任何键或值为null

27. java集合框架中泛型有什么优点?

     Java1.5引入了泛型,所有的集合接口和实现都大量地使用它,泛型允许我们为集合提供一个可以容纳的对象类型,因此,如果你添加其他类型的任何元素,他会子啊编译时保存,这避免了在运行时出现ClassCastException,因为你将会在编译时得到报错信息,泛型也使得代码整洁,我们不需要使用显示转换和instanceOf操作,它也会给运行时带来好处,因为不会产生类型检查的字节码指令

28. 迭代器fail-fast属性

     每次我们尝试获取下一个元素的时候,Iterator fail-fast属性检查当前集合结果中的任何改动,如果发现任何改动,它会抛出ConcurrentModificationException,Conllection中所有Iterator的实现都是按fail-fast来设计的(ConcurrentHashMap和CopyOnwriteArrayList这类并发集合类除外)

29. fail-fast与fail-safe有什么区别

      Iterator的fail-fast属性与当前的集合共同起作用,因此他会受到集合中任何改动的影响,Java.util包中所有集合类都被设计为fail-fast,而java.util.concurrent中的集合类都是fail-safe,fail-fast迭代器会抛出ConcurrentModificationException,而fail-safe迭代器从不抛出ConcurrentModificationException

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

memory_cood

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值