zoukankan      html  css  js  c++  java
  • Java集合框架总结

    java集合框架主要分为实现了Collection接口的List和Set、映射接口Map。

        |-- List 有序,元素都有索引,可重复。

        |-- Set 无序,不可以存储重复的元素。

        |-- Map中的每个元素包含一个Key和一个对应的Value。

    下图是java集合框架的体系结构

            


     Collection接口

    Collection接口是最基本的集合接口,他不提供直接的实现。
    Collection所表示的是一种规则,它所包含的元素都必须包含一条或多条原则.eg:有些允许重复,有些不允许重复;有些要求按照顺序插入而有些则是散列;有些支持排序有些不支持。
    所有实现了Collection接口的类都必须提供两套标准的构造函数,一个是无参,用于创建一个空的Collection;一个是带有Collection参数的有参构造函数,用于创造一个新的Collection,这个心得Collection与传进来的Collection具有相同的元素。

    Collection接口的一些公有方法

         主要就是增、删、判断、获取、取交集、变数组等。

          


    List

    List接口为Collection的直接接口。List代表的是有序的Collection,它用某种特定的顺序来维护元素的插入顺序。用户可对每个元素的精确的插入位置进行精确的控制,同时根据元素的索引获取元素。实现了List接口的集合主要有:ArrayList、LinkedList、Vector、Stack.

     

    |--Vector    线程同步,增删查询都很慢。

    |-- ArrayList    线程不同步,动态数组,ArrayList代替了Vector,允许插入null值,初始大小为10,擅长随机访问。

    |-- LinkedList    线程不同步,双向链表,增删元素非常快。

    |--Stack   继承自Vector,实现一个后进先出的堆栈。Stack在Vector的基础上增加了5个方法,使得其变为栈。Push、Pop、peek(获取栈顶)、empty、search(检测一个元素是否在堆中).


    set

    Set是一种不包括重复元素的Collection,他维持他的内部排序,允许null但仅能有一个,传入Set的元素必须不同。实现Set接口的集合有:EnumSet、HashSet、TreeSet.

     

    |--EnumSet 枚举专用的Set,所有元素都是枚举类型。

    |-- HashSet  底层是哈希表,线程不同步,无序,高效。HashSet堪称查询最快的集合,因为其内部是以HashCode实现的。它内部的顺序有哈希码来决定,所以不保证Set的迭代顺序。

    |-- LinkedHashSet  有序 ,HashSet的子类。

    |-- TreeSet  底层是二叉树, 线程不同步。 基于TreeMap,生成一个总是处于排序状态的Set,内部以TreeMap来实现,利用元素的自然顺序对元素进行排序,或者根据创建时提供的Comparator进行排序


    Map

    是由一系列键值对组成的集合,提供Key到Value的映射,不能存在相同的Key,实现Map的有:HashMap、TreeMap、HashTable、Properties、EnumMap .  Map要保证键的唯一性。

    |-- HashTable  底层哈希表,线程同步,不能存在Null键,Null值。线程同步,以哈希表的数据结构实现,解决冲突时与HashMap一样也是采用散列表的形式,不过性能比HashMap要低。

    |--HashMap  底层哈希表,线程不同步,不能存在Null键,Null值。 以哈希表数据结构实现,查找对象时通过hash值计算其位置,它是为快速查询而设计的,内部定义了一个Hash表数组(Entry[] table),元素会通过hash转化函数转为在数组中的索引,如果有冲突的,则用散列链表的形式串起来。

    |--LinkedHashMap  Map接口的哈希表和链接列表实现,具有预知的迭代顺序。

    |-- TreeMap 底层二叉树,可以对Map集合中的键进行制定顺序的排序。键以某种排序规则排序,内部以Red-balck(红-黑树)数据结构实现。实现了SortedMap接口。

    (Queue
    队列,主要分为两大类,一类是阻塞式队列,队列满了以后在插入会出现异常,ArrayBlockQueue、PriorityBlockingQueue、LinkedBlockingQueue。另一种队列则是双端队列,支持在头、尾两端插入和移除元素,主要包括:ArrayDeque、LinkedBlockingDeque、LinkedList。)


    下面按顺序对每一个容器进行详细讲解:


    List  --> Vector :

    可以使用整数索引访问,可以看成数组的访问方式,但是与数组不同的是Vector大小会自动增长。

    由 Vector 的 iterator 和 listIterator 所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代器自身的remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。

    Vector 的 elements 方法返回的 Enumeration 不是 快速失败的。

    点击查看ConcurrentModificationException和Fail-Fast机制


    List  --> ArrayList :

    实现了List接口,底层采用数组保存所有元素;动态数组,ArrayList是List接口的可变数组的实现;允许null值;不是同步的;实现了Cloneable()接口,级覆盖了clone()方法,能够被克隆。

    1.set(int index, E element):该方法首先调用rangeCheck(index) 来校验 index 变量是否超出数组范围,超出则抛出异常。而后,取出原 index 位置的值,并且将新的 element 放入 Index 位置,返回 oldValue。

    2.add(E e):该方法是将指定的元素添加到列表的尾部。当容量不足时,会调用 grow 方法增长容量。

    3.add(int index, E element):在 index 位置插入 element。

    4.addAll(Collection<? extends E> c) 和addAll(int index, Collection<? extends E> c) :将特定 Collection中的元素添加到 Arraylist 末尾。

    数组扩容有两个方法,1:通过一个 public 的方法ensureCapacity(int minCapacity) 来增加 ArrayList 的容量。2:而在存储元素等操作过程中,如果遇到容量不足,会调用priavte方法private void ensureCapacityInternal(int minCapacity) 实现。

    数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的 1.5 倍.


    List  --> LinkedList:

    LinkedList 与 ArrayList一样,都实现了List接口,但内部的数据结构有本质的不同,LinkedList 是基于链表实现的,所以在类中包含了first和last两个指针,所以插入删除效率高,但随机访问效率低。


    Set --> HashSet :

    HashSet是基于HashMap实现的,底层是采用HahsMap来保存数据的,HashSet中会有一个HashMap成员,在构造函数中对其初始化。因为HashSet是基于HashMap实现的,所以关于HashSet的操作基本都是调用HashMap的方法来实现的。但是我们需要覆盖HashCode()和Equals()方法(用来保证放入的对象的唯一性)。




    Set --> HashSet  -->LinkedHashSet:

     LinkedHashSet 继承HashSet、又基于LinkedHashMap来实现。

     LinkedHashSet 是一个Set的实现,存的不是键值对,而是值。LinkedHashSet是不同步的。

     LinkedHashSet 是Set的一个具体实现,其维护着一个运行于所有条目的双重链接列表,此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或访问顺序。


    Set --> TreeSet :

    不同步,当至少有一个线程修改了改set,则必须对外保持同步,一般是通过对自然封装该set的对象执行同步操作来完成,如果不存在这样的对象,则应该使用Collections.synchronizedSortedSet 方法来“包装”该 set。此操作最好在创建时进行,以防止对 set 的意外非同步访问:

    SortedSet s=Collections.synchronizedSortedSet(new TreeSet(...)); 此类的iterator方法返回的迭代器是 快速失败 的。


    Map --> HashTable:

    任何非null的对象都可以做键或值,为了成功的在哈希表中存储和获取对象,用作键的对象必须实现hashCode()和equals()方法。


    Map --> HashMap:

    基于哈希表的Map实现,HashMap实际上是一个链表散列的数据结构,即数组和链表的结合体。底层是一个数组结构,而每个存储空间又是一个链表,当创建HashMap的时候会初始化一个数组。

    允许存放Null Key和Null Value,当我们保存时,如果Key已经存在,则心得Value会覆盖旧的Value ,当我们执行put(此映射中关联指定值与指定键)操作时,先根据key的hashCode()计算出hash值,根据hash值得到这个元素在数组中的下标,如果数组中这个位置已经有元素了,则以链表的形式存放,新加入的放在链头,否则直接放到该位置。

    确定存储Key-Value时,不考虑Value值,仅仅根据Key决定位置。

    总结:HashMap在底层将Key-Value当成一个整体进行处理,这个整体是一个Entry对象,HashMap底层采用一个Entry[]数组来保存所有的Key-Value对。

    当HashMap中的元素越来越多时,Hash冲突的机率越来越高。为了提高查询效率,就要对HashMap扩容,但是HashMap扩容是很消耗性能的:原数组中的数据必须重新计算其在新数组中的位置,并放进去。数组自动扩容(扩展两倍)时发生在:元素个数 > 数组长度(默认是16) * 负载因子(默认是0.75),当然,默认值可在初始化时像构造中传递参数。

    负载因子是衡量一个散列表空间的散列程度的,负载因子越大表示填充的越满。(对使用链表法的散列表来说:负载因子越大,空间利用越充分,但查询效率就会降低)。

    HashMap的遍历方式:

    第一种:                                  

    Map map = new HashMap();
       Iterator iter = map.entrySet().iterator();
       while (iter.hasNext()) {
       Map.Entry entry = (Map.Entry) iter.next();
       Object key = entry.getKey();
       Object val = entry.getValue(); }
       }

     第二种:

    Map map = new HashMap();

    Iterator iter = map.keySet().iterator();

    while (iter.hasNext()) {

    Object key = iter.next();

    Object val = map.get(key);

    }

    第一种效率比第二种高。


    Map --> HashMap --> LinkedHashMap:

    此实现不是同步的。如果多个线程同时访问链接的哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须 保持外部同步。这一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在这样的对象,则应该使用Collections.synchronizedMap 方法来“包装”该映射。最好在创建时完成这一操作,以防止对映射的意外的非同步访问:

    Map m=Colections.synchronizedMap(new LinkedHashMap(...));


    Map --> TreeMap:

    基于红-黑树(Ren-Black tree)实现。该映射根据其键的自然映射展开,或者根据创建映射时提供的Comparator进行排序,具体取决于使用的构造方法。

    不同步,当至少有一个线程修改了改set,则必须对外保持同步,一般是通过对自然封装该set的对象执行同步操作来完成,如果不存在这样的对象,则应该使用Collections.synchronizedSortedSet 方法来“包装”该 set。此操作最好在创建时进行,以防止对 set 的意外非同步访问:

    SortedMap m=Collections.synchronizedSortedMap(new TreeMap(...)); 此类的iterator方法返回的迭代器是 快速失败 的。

  • 相关阅读:
    ELM学习
    《进化》从孤胆极客到高效团队
    《人件》《PeopleWare》 【美】Tom DeMarco TimothyLister 著 肖然 张逸 滕云 译
    《进化》从孤胆极客到高效团队---Notes1
    大数据第一部分LInux学习Note1
    C#Windows窗体初学
    C#初学笔记(Windows编程的基本概念)
    C#学习2017-9-26(读取文本文件和读取二进制文件)Notes9
    C#学习2017-9-26Notes8(文件和流,FileStream类)
    C#学习笔记Notes8(接口,接口实现,程序集,命名空间,using)
  • 原文地址:https://www.cnblogs.com/wyb628/p/6410341.html
Copyright © 2011-2022 走看看