集合(List、Set、Map)ArrayList、LinkedList、Vector、HashSet、LinkedHa ...

打印 上一主题 下一主题

主题 815|帖子 815|积分 2445

集合:

集合是动态生存多个任意对象,使用增加、删除元素时比力方便(自动扩缩容,不需要自己编写逻辑);
集合有单列集合Collection双列集合Map
        其中Collection有两个子接口:Set、List;
                List:有序、可以重复、支持索引、允许有多个null;
                        有三种遍历方式(迭代器、增强for、普通for (由于有索引));
                        List有实现类:ArrayList、LinkedList、Vector;
                Set:无序、不可以重复、最多有一个null、无索引;
                        有两种遍历方式:迭代器、增强for;
                        取出的序次和添加的序次不一样,但只要取了 一次,每次都一样;
                        Set有实现类:HashSet、LinkedHashSet、TreeSet;
        Map有三个实现类:HashMap、Hashtable、TreeMap;
                生存的是具有映射关系的键值对key-value;
                key和value可以是任何引用范例的数据,会封装到HashMap&Node中;
                key不允许重复,value可以重复;
                key可以为null,但只能有一个,value可以为null,可以有多个;
                一对key-value生存到Node中,而Node又实现Entry接口,以是Map有三种遍历方式:
   keySet:获取所有键的集合,用get(key)通过键获得对应的值;
  values:获取所有值的集合,但无法获取对应的键;
  entrySet:获取所有键值对的Set集合,每个元素都是一个Map.Entry对象,代表一个键值对;
  
迭代器Iterator:所有实现Collection接口的集合类都有一个iterator()方法,遍历集合,并返回一个实现了Iterator接口的对象,但他本身并不存放对象;
   Iterator.hashNext():判定是否还有下一个元素;
  Iterator.next():光标下移,并将下移后集合的元素返回;
          注:在iterator.next()前必须先使用iterator.hashNext来判定一下受否还有下一个元素,否则将会抛出非常;
增强for就是简易版的迭代器;

ArrayList:
           允许有null,可以多个null;
          是由数组来实现数据存储的;
          根本等同于Vector,除了ArrayList是线程不安全(但实行服从高),在多线程环境下不发起使用;
          扩容机制:ArrayList中维护了一个Object范例的数组elementDate:
                  translent Object[] elementDate;其中translent表现短暂的,该属性不会被序列化;
                  当创建ArrayList对象时,如果使用的是无参构造器,则elementDate初始容量为0,第一添加时,会扩容到10,再次扩容时elementDate容量会扩容到10*1.5=15,以此类推;
  如果使用的是指定大小的构造器,则elementDate初始容量为指定的大小,如果需要扩容时,则直接扩容为1.5倍,以此类推;
  
LinkedList:
           底层维护了一个双向链表;
          LinkedList中维护了两个属性first和last,其中first指向首节点,las指向尾节点;
          每个节点(Node对象)里又维护了三个属性pre、next、item,其中通过pre指向前一个节点、next指向后一个节点、item指向现实数据元素;
          LinkedList的添加、删除不是通过数组来完成的,而是通过调解节点引用来完成元素的添加和删除的,以是服从更高;
          线程不安全,没有实现同步;
  
LinkedList和ArrayList比力:
   ArrayList底层维护的是数组,由于有索引,以是改查服从更高一点;
  LinkedList底层维护的是链表,由于增删可以直接通过修改链表的指向即可,以是增删的服从更高一点;
  
Vector:
           底层也是一个对象数组:protected Object[] elementDate;
           Vector是线程同步的(即线程安全),Vector中的操作方法synchronized;
           扩容机制:创建Vector对象时,如果使用的是无参构造器,则elementDate初始容量为10,如果需要扩容时,会扩容到2倍,以此类推;
                  如果使用的是有参构造器,则elementDate的初始容量为指定的大小,如果需要扩容时,则直接扩容为2倍,以此类推;
  
HashSet:
           底层是HashMap,HashMap底层是数组+链表+红黑树;
          添加一个元素时,先通过盘算得到哈希值,然后转变成数组的索引值,根据索引值来看存储数据表table中的对应位置是否已经有存放的元素:
                  如果没有则直接添加到数组中(链表的头节点);
                  如果有则调用equals()来比力:如果相同就放弃添加;
                                                                  如果不相同则添加到链表的最后;
          由于HashSet的底层是HashMap,以是当一条链表的元素个数到达8,且数组中的个数 >= 64,就会进行树化(红黑树);
    扩展:
  根据 Java 官方文档和 HashMap 的源码实现,链表转换为红黑树的条件是:
  

  • 链表长度 >= 8:一个桶(bucket)中的链表长度到达了 8
  • 数组长度 >= 64:HashMap 的数组长度(即桶的数量)已经到达了 64 或更大。
  这两个条件必须同时满足,才会触发链表到红黑树的转换。如果其中一个条件不满足,纵然链表长度到达了 8,也不会进行树化。它仍然还会保持链表的情势。
  
LinkedHashSet:
           底层是一个LinkedHashMap,底 层维护了一个数组+双向链表;
          每一个节点有属性before和after,如许就形成了双向链表;
          在添加一个元素时,先求哈希值来确定元素位置,如果没有相同的则直接添加到双向链表中,如果相同则不添加(和HashSet一样):
          如果相称:不实行任何操作,由于集合不允许重复元素;
          如果不相称:将新节点插入到双向链表的尾部,并更新相关指针,如:
                  tail.after = newElement;
                  newElement.before = tail;
                  tail = newElement;
                  其中tail尾节点,newElement新添加的元素;
  
HashMap:
           当添加相同的key时,则会覆盖原来的key-value,等同于 修改,但key不会被替换,value会被替换;
          没有实现同步,线程不安全;
          底层维维护了Node范例的数组table : Node<K,V>[] table 数组,默认为null;
          扩容机制:当创建对象时,加载因子初始为0.75;
                  当添加元素时,通过key的哈希值来得出在table的索引,判定该索引处是否有元素:
                          如果没有直接添加;
                         如果有再判定key是否相称:
                                  如果相称则覆盖(替换value);
                                  如果key不相称则需判定是树结构还是链表结构并作出相应处理:
                                          如果是链表:将新节点插入链表尾部;
                                          如果是红黑树:按照红黑树规则插入新节点;
          第一次添加需扩容table容量为16,临界值16*0.75=12;以后再扩容,table和临界值都扩大两倍32和24,以此类推;
          当table大小>= 64且一条链上的元素个数凌驾默认值8,就会树化(红黑树),链表会转换为红黑树,以进步查找服从; 相反地,如果某个红黑树中的节点数减少到小于 6,它会被转换回链表,以节省空间;
  
HashSet 和 HashMap 的区别:
   HashSet:
          是 Java 集合框架中的一个类,它实现了 Set 接口。HashSet 不包管元素的序次,并且不允许存储重复元素。它是基于 HashMap 实现的,详细来说,HashSet 使用 HashMap 的键来存储元素,而值则使用一个静态的对象(通常是一个 PRESENT 标志),由于 HashSet 只关心元素是否存在于集合中,而不关心它们关联的值。
          使用场景:
                  当你需要一个不包罗重复元素的集合时,HashSet 是一个很好的选择;
                  对于频繁的插入、删除和查找操作,HashSet 提供了高效的性能;
  
  HashMap:
          是 Java 集合框架中的一个类,它实现了 Map 接口。HashMap 存储键值对(key-value pairs),并且允许一个 null 键和多个 null 值。它不包管键值对的序次,并且基于哈希表(hash table)实现。
          使用场景:
                  当你需要一个键值对映射关系,并且需要高效地进行插入、删除和查找操作时,HashMap 是一个很好的选择;
                       它适用于大多数不需要保持插入序次的场景;
  
  功能差异:
          HashSet 关注的是元素的存在性,不允许重复元素,也不关心元素之间的关联值;
          HashMap 关注的是键值对的映射关系,允许一个 null 键和多个 null 值;
  
  性能相似:
          两者都依赖于哈希表结构,因此在插入、删除和查找操作上具有相似的性能特点;
  
Hashtable(了解即可):
        根本和HashMap一样,但key和value都不能为null,否则会抛出NullPointerExceptioon非常;        
        是线程安全的;
        它是一个更古老的类,最早出现在 Java 1.0 中。
        历史缘故原由:
     Hashtable 是基于早期的 Java 计划理念,当时的计划目标是提供一种线程安全的哈希表实现,而不允许 null 键和值是为了简化内部实现和避免潜伏的并发题目;
                Hashtable 最初计划时,Java 还没有引入泛型(generics),并且对 null 的处理相对简朴。为了确保线程安全和简化实现,Hashtable 决定不支持 null 键和值。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表