首页 > 编程语言 >Java-Java集合

Java-Java集合

时间:2022-08-25 09:35:57浏览次数:124  
标签:JDK1.8 Java HashMap 元素 链表 线程 Hashtable 集合

修订记录 版本 是否发布
2020-01-05 v1.0

一、List,Set,Map三者的区别

  • List(对付顺序的好帮⼿): List接⼝存储⼀组不唯⼀(可以有多个元素引⽤相同的对象),有
    序的对象
  • Set(注重独⼀⽆⼆的性质): 不允许重复的集合。不会有多个元素引⽤相同的对象。
  • Map(⽤Key来搜索的专家): 使⽤键值对存储。Map会维护与Key有关联的值。两个Key可以引⽤相
    同的对象,但Key不能重复,典型的Key是String类型,但也可以是任何对象。

二、Arraylist 与 LinkedList 区别

  • 是否保证线程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安
    全;
  • 底层数据结构: Arraylist 底层使⽤的是 Object 数组; LinkedList 底层使⽤的是
    双向链表数据结构(JDK1.6之前为双向循环链表,JDK1.7取消了循环。注意双向链表和双向循环链
    表的区别,下⾯有介绍到!)
  • 插⼊和删除是否受元素位置的影响: ① ArrayList 采⽤数组存储,所以插⼊和删除元素
    的时间复杂度受元素位置的影响。
  • 是否⽀持快速随机访问: LinkedList 不⽀持⾼效的随机元素访问,⽽ ArrayList ⽀
    持。
  • 内存空间占⽤: ArrayList的空 间浪费主要体现在在list列表的结尾会预留⼀定的容量空
    间,⽽LinkedList的空间花费则体现在它的每⼀个元素都需要消耗⽐ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。

三、ArrayList 与 Vector 区别呢?为什么要⽤Arraylist取代Vector呢

  • Vector 类的所有⽅法都是同步的。可以由两个线程安全地访问⼀个Vector对象、但是⼀个线程访问
    Vector的话代码要在同步操作上耗费⼤量的时间。
  • Arraylist 不是同步的,所以在不需要保证线程安全时建议使⽤Arraylist。

四、HashMap 和 Hashtable 的区别

  1. 线程是否安全: HashMap 是⾮线程安全的,HashTable 是线程安全的;HashTable 内部的⽅法
    基本都经过 synchronized 修饰。(如果你要保证线程安全的话就使⽤ ConcurrentHashMap
    吧!);
  2. 效率: 因为线程安全的问题,HashMap 要⽐ HashTable 效率⾼⼀点。另外,HashTable 基本被
    淘汰,不要在代码中使⽤它;
  3. 对Null key 和Null value的⽀持: HashMap 中,null 可以作为键,这样的键只有⼀个,可以
    有⼀个或多个键所对应的值为 null。。但是在 HashTable 中 put 进的键值只要有⼀个 null,
    直接抛出 NullPointerException。
  4. 初始容量⼤⼩和每次扩充容量⼤⼩的不同 : ①创建时如果不指定容量初始值,Hashtable 默认
    的初始⼤⼩为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化⼤⼩为16。之后
    每次扩充,容量变为原来的2倍。②创建时如果给定了容量初始值,那么 Hashtable 会直接使⽤
    你给定的⼤⼩,⽽ HashMap 会将其扩充为2的幂次⽅⼤⼩(HashMap 中的 tableSizeFor() ⽅
    法保证,下⾯给出了源代码)。也就是说 HashMap 总是使⽤2的幂作为哈希表的⼤⼩,后⾯会介
    绍到为什么是2的幂次⽅。
  5. 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了⼤的变化,当链表⻓度⼤于
    阈值(默认为8)时,将链表转化为红⿊树,以减少搜索时间。Hashtable 没有这样的机制。

五、HashMap 和 HashSet区别

HashMap HashSet
实现了Map接⼝ 实现Set接⼝
存储键值对 仅存储对象
调⽤ put()向map中添加元素 调⽤ add()⽅法向Set中添加元素
HashMap使⽤键(Key)计算Hashcode HashSet使⽤成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()⽅法⽤来判断对象的相等性

六、HashMap的底层实现

JDK1.8之前
JDK1.8 之前 HashMap 底层是 数组和链表 结合在⼀起使⽤也就是链表散列。HashMap 通过 key 的
hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置
(这⾥的 n 指的是数组的⻓度),如果当前位置存在元素的话,就判断该元素与要存⼊的元素的 hash
值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。

所谓扰动函数指的就是 HashMap 的 hash ⽅法。使⽤ hash ⽅法也就是扰动函数是为了防⽌⼀些实现
⽐较差的 hashCode() ⽅法 换句话说使⽤扰动函数之后可以减少碰撞。

JDK1.8之后
相⽐于之前的版本, JDK1.8之后在解决哈希冲突时有了᫾⼤的变化,当链表⻓度⼤于阈值(默认为8)
时,将链表转化为红⿊树,以减少搜索时间。

TreeMap、TreeSet以及JDK1.8之后的HashMap底层都⽤到了红⿊树。红⿊树就是为了解决⼆叉查找树
的缺陷,因为⼆叉查找树在某些情况下会退化成⼀个线性结构。

七、ConcurrentHashMap 和 Hashtable 的区别

ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的⽅式上不同

  • 底层数据结构: JDK1.7的 ConcurrentHashMap 底层采⽤ 分段的数组+链表 实现,JDK1.8 采⽤
    的数据结构跟HashMap1.8的结构⼀样,数组+链表/红⿊⼆叉树。Hashtable 和 JDK1.8 之前的
    HashMap 的底层数据结构类似都是采⽤ 数组+链表 的形式,数组是 HashMap 的主体,链表则是
    主要为了解决哈希冲突⽽存在的;
  • 实现线程安全的⽅式(重要)① 在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶
    数组进⾏了分割分段(Segment),每⼀把锁只锁容器其中⼀部分数据,多线程访问容器⾥不同数
    据段的数据,就不会存在锁竞争,提⾼并发访问率。 到了 JDK1.8 的时候已经摒弃了Segment的
    概念,⽽是直接⽤ Node 数组+链表+红⿊树的数据结构来实现,并发控制使⽤ synchronized 和
    CAS 来操作。(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线
    程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只
    是为了兼容旧版本;② Hashtable(同⼀把锁) :使⽤ synchronized 来保证线程安全,效率⾮常
    低下。当⼀个线程访问同步⽅法时,其他线程也访问同步⽅法,可能会进⼊阻塞或轮询状态,如
    使⽤ put 添加元素,另⼀个线程不能使⽤ put 添加元素,也不能使⽤ get,竞争会越来越激烈
    效率越低。

标签:JDK1.8,Java,HashMap,元素,链表,线程,Hashtable,集合
From: https://www.cnblogs.com/BCX-1024/p/javajava-ji-he.html

相关文章

  • Java-Java集合排序
    一、ListMap排序修订记录版本是否发布2020-01-25v1.0是一、ListMap排序Java中list里面存放map,根据map中的某一个或多个字段进行排序importjava.u......
  • Java-Java中的运算符
    一、Java&、&&、|、||、^、<<、>>、~、>>>等运算符&(按位与)&&(逻辑与)|(按位或)||(逻辑或)^(异或运算符)<<(左移运算符)>>(右移运算符)~(取反运算符)>>>(无符号右移运算符)二......
  • Java-Java操作SFTP工具类
    一、SFTP工具类二、配置文件Bean修订记录版本是否发布2020-08-03v1.0是一、SFTP工具类importcom.*.*.common.util.FileUtil;importcom.*.*.comm......
  • Java8 对list集合中的bigdecimal进行分组求和,均值,最大值,最小值
     文章目录需求中对数值进行求和的非常多,但java8对bigdecimal求和没有封装新建接口ToBigDecimalFunction新建工具类CollectorsUtil实体类Person 需求中对......
  • Java 获取三天前时间
    (1)根据newDate().getTime()获取从1970年1月1日0点0分到目前的毫秒数计算三天前的时间:DatedateBy3Days=newDate(newDate().getTime()-3*24*60*60*1000);  Sim......
  • 不使用骨架创建maven的java工程、使用骨架创建maven的web工程
    不使用骨架创建maven的java工程    使用骨架创建maven的web工程  选入web框架 ......
  • Java函数式编程
    函数式编程-Stream流1.概述1.1为什么学?能够看懂公司里的代码大数量下处理集合效率高代码可读性高消灭嵌套地狱//查询未成年作家的评分在70以上的书籍由于洋流......
  • Java学习笔记5
    抽象类抽象类和其中抽象方法由abstract修饰,继承抽象类的所有方法必须由子类实现。Java的类是单继承,但是可以继承多个接口抽象类不能new实例化接口普通类:只有具体实......
  • Java继承
    继承概述由来:多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。如图所示:其中,多个类可以......
  • Java中字节流的总结及代码练习
    Java中的字节流在描述字节流时,先知道什么是流流可以分为:输入流和输出流输入流和输出流示意图:字节流读取内容:二进制,音频,视频优缺点:可以保证视频音频无损,效率低,没有缓......