JAVA集合

JAVA集合接口继承关系和实现

在这里插入图片描述

  • 集合类存放在java.util包中,主要有set(集)、list(列表)、map(映射)。
  • Collection:是集合List、Set、Queue的基本接口
    在这里插入图片描述
  • Iterator:迭代器,可以通过迭代器遍历集合中的数据
  • Map:映射表的基本接口
    在这里插入图片描述

List

  • List是有序、可重复的Collection,java List有三个实现类:ArrayList、Vector、LinkedList。
    在这里插入图片描述

ArrayList

  • 内部通过数组实现,允许对元素进行随机访问。
  • 缺点:每个元素之间不能有间隔,当数组大小不满足时,需要增加存储能力,要将已经有数组的数据复制到新的存储空间中。
  • 适合随机查找和遍历,不适合插入和删除

Vector

  • 通过数组实现
  • 支持线程同步,某一时刻只有一个线程能写Vector,避免多线程同时写引起的不一致问题,但实现同步需要很高的花费
  • 查询快,增删慢,效率低

LinkList

  • 链表结构存储数据
  • 适合动态插入和删除
  • 随机访问和遍历速度较慢
  • 提供操作表头和表尾元素,可以当做堆栈、队列和双向队列使用

set

  • Set用于存储无序、唯一的元素
  • 对象的相等性本质是对象hashCode值判断的
  • 两个不同的对象相等,必须覆盖Object的hashCode方法和equals方法
    在这里插入图片描述

HashSet

  • 哈希表存放的是哈希值
  • 存储元素的顺序不是按照存入的顺序,而是按照哈希值存的,取数据也是按照哈希值取数。
  • 元素的哈希值是通过元素的hashCode方法获取
  • HashSet首先判断两个元素的哈希值,如果哈希值一样,接着比较equals方法,如果equals结果为true,HashSet视为同一个元素。
  • 哈希值相同,equals为false的元素存储:在同一的哈希值下顺延(哈希值相同的元素放在一个哈希桶中),哈希一样的存在一列
  • HashSet通过hashCode值来确定原则在内存中的位置,一个hashCode位置上可以存放多个元素

LinkedHashSet

  • LinkedHashSet是一个哈希表和链表的结合.
  • LinkedHashSet而言,它继承与HashSet、又基于LinkedHashMap来实现的。
  • LinkedHashSet底层使用LinkedHashMap来保存所有元素
  • LinkedHashSet继承于HashSet,其所有的方法操作上又与HashSet相同,因此LinkedHashSet 的实现上非常简单,只提供了四个构造方法,并通过传递一个标识参数,调用父类的构造器,底层构造一个LinkedHashMap来实现,在相关操作上与父类HashSet的操作相同,直接调用父类HashSet的方法即可。

TreeSet

  • 使用二叉树的原理对新add()的对象按照指定的顺序排序,每增加一个对象都会进行排序,将对象插入的二叉树指定位置。
  • Interger和String对象都可以通过默认的TreeSet排序,自定义的类的对象不可用,自定义的类必须实现Comparable接口,并且覆写相应的compareTo()方法,才可以正常使用。
  • 在覆写compare()函数时,要返回相应的值才能使TreeSet按照一定的规则来排序
  • 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

Map

HashMap

  • HashMap根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。
  • HashMap最多只允许一条记录的键为null,允许多条记录的值为null
  • HashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。
  • 如果需要满足线程安全,可以用 Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap
  • JAVA7实现的HashMap
    在这里插入图片描述
    • HashMap 里面是一个数组,然后数组中每个元素是一个单向链表。
    • Entry 包含四个属性:key, value, hash 值和用于单向链表的 next。
    • 参数:
      • capacity:当前数组容量,始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍。
      • loadFactor:负载因子,默认为 0.75。
      • threshold:扩容的阈值,等于 capacity * loadFactor。
  • JAVA8实现的HashMap
    在这里插入图片描述
    • Java8实现的HashMap最大的不同就是利用了红黑树,所以其由 数组+链表+红黑树 组成。
    • 当链表中的元素超过了8个以后,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)。

HashTable

  • 它承自Dictionary类。
  • 线程安全,任一时间只有一个线程能写Hashtable,不允许使用null值和null键。
  • 使用synchronized来锁住整张Hash表来实现线程安全,即每次锁住整张表让线程独占,相当于所有线程进行读写时都去竞争一把锁,导致效率非常低下。
  • Hashtable不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换。

TreeMap

  • TreeMap实现SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。
  • 如果使用排序的映射,建议使用TreeMap
  • 在使用TreeMap时,key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常。

LinkedHashMap

  • HashMap的一个子类,是基于HashMap和双向链表来实现的。
  • 保存了记录的插入顺序,LinkedHashMap有序,可分为插入顺序和访问顺序两种。如果是访问顺序,那put和get操作已存在的Entry时,都会把Entry移动到双向链表的表尾(其实是先删除再插入)。
  • 在用Iterator遍历时,先得到的记录时限插入的,也可以在构造时带参数,按照访问次序排序。
  • LinkedHashMap存取数据,还是跟HashMap一样使用的Entry[]的方式,双向链表只是为了保证顺序
  • LinkedHashMap是线程不安全的。

ConcurrentHashMap

concurrentHashMap内部构造图

  • Segment段
    • ConcurrentHashMap 由一个个 Segment 组成,Segment 代表”部分“或”一段“或“槽”,也可以称为“分段锁”。
    • 一个 Segment 其实就是一个类 Hash Table 的结构,Segment 内部维护了一个链表数组。
  • 线程安全(Segment 继承 ReentrantLock 加锁)
    • Segment 通过继承 ReentrantLock 来进行加锁,所以每次需要加锁的操作锁住的是一个 segment,这样只要保证每个 Segment 是线程安全的,也就实现了全局的线程安全。
  • 锁分离技术
    • ConcurrentHashMap采用了二次hash的方式,第一次hash将key映射到对应的segment,而第二次hash则是映射到segment的不同桶(bucket)中
    • 二次hash的原因:为了构造分离锁,使得对于map的修改不会锁住整个容器,提高并发能力。
  • JDK1.7的ConcurrentHashMap
    在这里插入图片描述
    • ConcurrentHashMap是由 Segment 数组、HashEntry 组成,和 HashMap 一样,仍然是数组加链表。
    • 和 HashMap 非常类似,唯一的区别就是其中的核心数据如 value ,以及链表都是 volatile 修饰的,保证了获取时的可见性
    • ConcurrentHashMap 支持 CurrencyLevel (Segment 数组数量)的线程并发。CurrencyLevel 默认是 16,最多可以同时支持 16 个线程并发写,只要它们的操作分别分布在不同的 Segment 上。concurrencyLevel 一经指定,不可改变
    • 如果ConrruentHashMap需要扩容,ConcurrentHashMap不会增加Segment的数量,而只会增加Segment中链表数组的容量大小,而只需要对Segment里面的元素做一次rehash就可以了。
  • JDK1.8中的ConcurrentHashMap
    在这里插入图片描述
    • 利用 CAS 算法,底层依然由“数组”+链表+红黑树的方式思想,但是为了做到并发,又增加了很多辅助的类。
    • ConcurrentHashMap 使用了 happens-before 规则来实现。
    • 采用红黑树之后可以保证查询效率(O(logn)),甚至取消了 ReentrantLock 改为了 synchronized
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值