• 集合的介绍(完全版)


    集合和数组的区别

    Collections 是一个帮助类,这个类提供了很多对集合的各种操作的静态方法。

    Collection  接口的接口 对象的集合(单值集合)

      1. List(元素按进入先后有序保存,可重复 )
        1. Linkedlist   接口实现类, 底层结构是链表, 插入删除快,查询慢, 没有同步, 线程不安全,效率高
        2. ArrayList    接口实现类, 底层结构是数组, 随机访问,查询快,增删慢, 没有同步, 线程不安全,效率高
        3. Vector        接口实现类, 底层结构是数组, 同步, 线程安全,效率高
          1.      Stack 是Vector类的实现类 
      2. Set(存储和取值顺序不一致,即无序的,仅接收一次,不可重复,并做内部排序
        1. HashSet    使用hash表(数组)存储元素 
          1.  LinkedHashSet     链表维护元素的插入次序 
        2. TreeSet     底层实现为二叉树,元素排好序
      1. Queue(队列) 

    Map接口 键值对的集合 (双列集合)

      1. TreeMap      红黑树对所有的key进行排序
      2. HashMap     接口实现类 ,没有同步, 线程不安全
        1. LinkedHashMap 双向链表和哈希表实现
        2. WeakHashMap 
      3. HashTable   接口实现类, 同步, 线程安全 
      4. IdentifyHashMap

    Iterator

      

    从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器:

      一种是集合(Collection),存储一个元素集合;

      另一种是图(Map),存储键/值对映射。

      Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap,HashTable 等等。

    集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:

    • 接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象

    • 实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。

    • 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

    除了集合,该框架也定义了几个 Map 接口和类。Map 里存储的是键/值对。尽管 Map 不是集合,但是它们完全整合在集合中。


     

    Collection 接口

    Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。

    Collection 接口存储一组不唯一,无序的对象。

     List 接口

    List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。

    List 接口存储一组不唯一,有序(插入顺序)的对象。

    Set接口

    Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。

    Set 接口存储一组唯一,无序的对象。

      SortedSet   继承于Set保存有序的集合。

    Map接口

      Map 接口存储一组键值对象,提供key(键)到value(值)的映射。

      Map.Entry  描述在一个Map中的一个元素(键/值对)。是一个Map的内部类。

      SortedMap 继承于 Map,使 Key 保持在升序排列。

    Enumeration 这是一个传统的接口和定义的方法,通过它可以枚举(一次获得一个)对象集合中的元素。这个传统接口已被迭代器取代。

    Set和List的区别

    • 1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。

    • 2. Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>

    • 3. List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。

    • 4.List,Set都是继承自Collection接口,Map则不是

        


     集合类

    List

      Java提供了一套实现了Collection接口的标准集合类。其中一些是具体类,这些类可以直接拿来使用,而另外一些是抽象类,提供了接口的部分实现。

      AbstractCollection 实现了大部分的集合接口。

      AbstractList  继承于AbstractCollection 并且实现了大部分List接口。

      AbstractSequentialList 继承于 AbstractList ,提供了对数据元素的链式访问而不是随机访问。

    LinkedList  

      该类实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List。例如:

    Listlist=Collections.synchronizedList(newLnkedList(...));

      LinkedList 查找效率低。查找慢由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个元素, 后一个元素记住前一个元素. 这样的增删效率较高但查询时需要一个一个的遍历, 所以效率较低。

    ArrayList

      该类也是实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用。ArrayList 增长当前长度的50%,插入删除效率低。由于是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 所以慢。数组是可以直接按索引查找, 所以查找时较快。

    1 public ArrayList(int initialCapacity)//构造一个具有指定初始容量的空列表。    
    2 public ArrayList()      //默认构造一个初始容量为10的空列表。    
    3 public ArrayList(Collection<? extends E> c)//构造一个包含指定 collection 的元素的列表

    Vector  和ArrayList原理相同, 但线程安全, 效率略低 和ArrayList实现方式相同, 但考虑了线程安全问题, 所以效率略低

    1 public Vector()//使用指定的初始容量和等于0的容量增量构造一个空向量。    
    2 public Vector(int initialCapacity)//构造一个空向量,使其内部数据数组的大小,其标准容量增量为零。    
    3 public Vector(Collection<? extends E> c)//构造一个包含指定 collection 中的元素的向量    
    4 public Vector(int initialCapacity,int capacityIncrement)//使用指定的初始容量和容量增量构造一个空的向量 

    ArrayList与LinkedList的区别和适用场景

      Arraylist:
    优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
    缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。

      LinkedList:
    优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景
    缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
    适用场景分析:
    当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。

    ArrayList和Vector都是用数组实现的,主要有这么三个区别:

    (1)Vector是多线程安全的,线程安全就是说多线程访问同一代码,不会产生不确定的结果。而ArrayList不是,这个可以从源码中看出,Vector类中的方法很多有synchronized进行修饰,这样就导致了Vector在效率上无法与ArrayList相比;
    (2)两个都是采用的线性连续空间存储元素,但是当空间不足的时候,两个类的增加方式是不同。
    (3)Vector可以设置增长因子,而ArrayList不可以。
    (4)Vector是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用。
    适用场景分析:
    1.Vector是线程同步的,所以它也是线程安全的,而ArrayList是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用ArrayList效率比较高。
    2.如果集合中的元素的数目大于目前集合数组的长度时,在集合中使用数据量比较大的数据,用Vector有一定的优势。

    Set

        AbstractSet  继承于AbstractCollection 并且实现了大部分Set接口。

    HashSet

      该类实现了Set接口,元素无序且唯一,允许包含值为null的元素,但最多只能一个。

    底层数据结构采用哈希表实现线程不安全,效率高,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。

    hashSet存储元素的原理:

      往hashSet中存储数据时首先会调用元素的hashCode()方法得到元素的哈希码值,然后根据hash码值经过运算计算出该元素在哈希表中的位置。

      情况1:计算出的位置没有元素,则直接存储;

      情况2:计算出的位置已经存在其他元素,则通过调用元素的equals()方法与之比较一次。
    具体实现唯一性的比较过程:

      存储元素首先会使用hash()算法函数生成一个int类型hashCode散列值,然后与已经的所存储的元素的hashCode值比较,如果hashCode不相等,则所存储的两个对象一定不相等,此时存储当前的新的hashCode值处的元素对象;

      如果hashCode相等,存储元素的对象还是不一定相等,此时会调用equals()方法判断两个对象的内容是否相等,如果内容相等,那么就是同一个对象,无需存储;

      如果比较的内容不相等,那么就是不同的对象,就该存储了,此时就要采用哈希的解决地址冲突算法,在当前hashCode值处类似一个新的链表, 在同一个hashCode值的后面存储不同的对象,这样就保证了元素的唯一性。
      

    Set的实现类的集合对象中不能够有重复元素,HashSet也一样他是使用了一种标识来确定元素的不重复,HashSet用一种算法来保证HashSet中的元素是不重复的, HashSet采用哈希算法,底层用数组存储数据。默认初始化容量16,加载因子0.75。
    Object类中的hashCode()的方法是所有子类都会继承这个方法,这个方法会用Hash算法算出一个Hash(哈希)码值返回,HashSet会用Hash码值去和数组长度取模, 模(这个模就是对象要存放在数组中的位置)相同时才会判断数组中的元素和要加入的对象的内容是否相同,如果不同才会添加进去。
    Hash算法是一种散列算法。
    Set hs=new HashSet();

    hs.add(o);
    |
    o.hashCode();
    |
    o%当前总容量 (0–15)
    |
    是否发生冲突—————–不发生冲突,直接存放
    |
    | 发生冲突


    o1.equals(o2)——————-假(不相等),找一个空位添加
    |
    | 是(相等)
    不添加
    覆盖hashCode()方法的原则:
    1、一定要让那些我们认为相同的对象返回相同的hashCode值
    2、尽量让那些我们认为不同的对象返回不同的hashCode值,否则,就会增加冲突的概率。
    3、尽量的让hashCode值散列开(两值用异或运算可使结果的范围更广)
    HashSet 的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成,我们应该为保存到HashSet中的对象覆盖hashCode()和equals(),因为再将对象加入到HashSet中时,会首先调用hashCode方法计算出对象的hash值,接着根据此hash值调用HashMap中的hash方法,得到的值& (length-1)得到该对象在hashMap的transient Entry[] table中的保存位置的索引,接着找到数组中该索引位置保存的对象,并调用equals方法比较这两个对象是否相等,如果相等则不添加,注意:所以要存入HashSet的集合对象中的自定义类必须覆盖hashCode(),equals()两个方法,才能保证集合中元素不重复。在覆盖equals()和hashCode()方法时, 要使相同对象的hashCode()方法返回相同值,覆盖equals()方法再判断其内容。为了保证效率,所以在覆盖hashCode()方法时, 也要尽量使不同对象尽量返回不同的Hash码值。

    如果数组中的元素和要加入的对象的hashCode()返回了相同的Hash值(相同对象),才会用equals()方法来判断两个对象的内容是否相同。

    参考实例

     TreeSet

      该类实现了Set接口,可以实现排序等功能。

      底层数据结构采用二叉树来实现,元素唯一且已经排好序;唯一性同样需要重写hashCode和equals()方法,二叉树结构保证了元素的有序性。

    TreeSet要注意的事项:

      1.往TreeSet中添加元素的时候,如果元素具备自然排序的特点,那么TreeSet会根据元素的自然顺序特性进行排序存储。

      2.往TreeSet中添加元素的时候,如果元素不具备自然排序的特点,那么元素所属的类就必须实现Comparable接口,把比较的规则定义在Comparable()方法上。

      3.往TreeSet中添加元素的时候,如果元素不具备自然排序的特点,元素所属的类也没有实现Comparable接口,那么在创建TreeSet时就必须传入一个比较器对象。

      根据构造方法不同,分为自然排序(无参构造)和比较器排序(有参构造),自然排序要求元素必须实现Comparable接口,并重写里面的compareTo()方法,元素通过比较返回的int值来判断排序序列,返回0说明两个对象相同,不需要存储;比较器需要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法;

    TreeSet和HashSet的区别 

    1.TreeSet 是二差树(红黑树的树据结构)实现的,Treeset中的数据是自动排好序的,不允许放入null值
    2.HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束
    3.HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例

    适用场景分析:HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。为快速查找而设计的Set,我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet。


      小结:Set具有与Collection完全一样的接口,因此没有任何额外的功能,不像前面有两个不同的List。实际上Set就是Collection,只 是行为不同。(这是继承与多态思想的典型应用:表现不同的行为。)Set不保存重复的元素。
    Set 存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。

    Map


        AbstractMap 实现了大部分的Map接口。

    HashMap 
      HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
      该类实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。

       JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。
    HasMap 中带有初始容量的构造函数

    TreeMap 
      继承了AbstractMap,并且使用一颗树。

    WeakHashMap 
      继承AbstractMap类,使用弱密钥的哈希表。

    LinkedHashMap 
      继承于HashMap,使用元素的自然顺序对元素进行排序.底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。

    IdentityHashMap 
      继承AbstractMap类,比较文档时使用引用相等。IdentityHashMap和HashMap的具体区别,IdentityHashMap使用 == 判断两个key是否相等,而HashMap使用的是equals方法比较key值.

    小结:
    HashMap 非线程安全
    HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],为了优化HashMap空间的使用,您可以调优初始容量和负载因子。

    TreeMap:非线程安全基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。

    适用场景分析:
    HashMap和HashTable:HashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKey()方法。HashTable同步的,而HashMap是非同步的,效率上比HashTable要高。HashMap允许空键值,而HashTable不允许。

    HashMap:适用于Map中插入、删除和定位元素。
    Treemap:适用于按自然顺序或自定义顺序遍历键(key)。

    5.线程安全集合类与非线程安全集合类
    LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
    HashMap是非线程安全的,HashTable是线程安全的;
    StringBuilder是非线程安全的,StringBuffer是线程安全的。

    数据结构
    ArrayXxx:底层数据结构是数组,查询快,增删慢
    LinkedXxx:底层数据结构是链表,查询慢,增删快
    HashXxx:底层数据结构是哈希表。依赖两个方法:hashCode()和equals()
    TreeXxx:底层数据结构是二叉树。两种方式排序:自然排序和比较器排序


    类描述

    Vector 

      该类和ArrayList非常相似,但是该类是同步的,可以用在多线程的情况,该类允许设置默认的增长长度,默认扩容方式为原来的2倍。

    Stack 
      栈是Vector的一个子类,它实现了一个标准的后进先出的栈。

    Dictionary 
      Dictionary 类是一个抽象类,用来存储键/值对,作用和Map类相似。

    Hashtable 

      Hashtable 是 Dictionary(字典) 类的子类,位于 java.util 包中。

    Properties 
      Properties 继承于 Hashtable,表示一个持久的属性集,属性列表中每个键及其对应值都是一个字符串。

    BitSet
      一个Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加。


    集合算法



    集合框架定义了几种算法,可用于集合和映射。这些算法被定义为集合类的静态方法。

    在尝试比较不兼容的类型时,一些方法能够抛出 ClassCastException异常。当试图修改一个不可修改的集合时,抛出UnsupportedOperationException异常。

    集合定义三个静态的变量:EMPTY_SET,EMPTY_LIST,EMPTY_MAP的。这些变量都不可改变。

    算法描述  Collection Algorithms  这里是一个列表中的所有算法实现。

    如何使用迭代器



    通常情况下,你会希望遍历一个集合中的元素。例如,显示集合中的每个元素。

    一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但是还有一种方法是采用迭代器遍历集合框架,它是一个对象,实现了Iterator 接口或ListIterator接口。

    迭代器,使你能够通过循环来得到或删除集合的元素。ListIterator 继承了Iterator,以允许双向遍历列表和修改元素。

    迭代器方法描述  使用 Java Iterator  这里通过实例列出Iterator和listIterator接口提供的所有方法。


    参考链接:

    Java集合详解

    Set和List集合对比

    java集合对比汇总

  • 相关阅读:
    DataGridView 中的复选框DataGridViewCheckBoxColumn 添加验证
    DataGridView删除行 提示 索引-1没有值 索引0没有值 等 解决办法
    convert mov mp4 to jpg
    拼图
    remove ad of chrome how to block ad of newssysstem.net
    redis3常用命令
    python_爬虫总结
    boot_自定义异常
    简答题总结
    springmvc_文件上传
  • 原文地址:https://www.cnblogs.com/chen2608/p/10987292.html
Copyright © 2020-2023  润新知