Java.util包简单总结

article/2025/10/7 8:24:02

之前听一位老师讲过,学Java的程序员,lang包和util包至少是要过一遍的。
很惭愧的是,从入门到现在,我还没完整的探究过这两个基础包。
今天借着跟公司小伙伴分享的机会,把util包简单的梳理一遍。由于最近加班很多,此篇先做粗略总结,日后有时间再完善。

1. util包的框架

常用的集合类主要实现两个“super接口”而来:CollectionMap

1.1 Collection有两个子接口:ListSet

这里写图片描述

List特点是元素有序,且可重复。实现的常用集合类有ArrayListLinkedList,和Vector(线程安全)。

Set特点是元素无序,不可重复。实现的常用集合类有HashSetLinkedHashSetTreeSet(可排序)

1.2 Map是key、value键值对的集合

这里写图片描述

特点是key值无序不可重复,value值可重复(这样表述其实不太准确,因为实际上key和value是绑定在一起的)。常用的有HashMapHashTable(线程安全),TreeMap(可排序)。

1.3 其余重要接口和类

上面是util包中的集合框架,一般Java教材里面都会讲到。但我们深入研究一下,会发现还有其余几个重要的内容:

  • Iterator:迭代接口
    集合类实现该接口后便具有了迭代功能。最简单的迭代实现是ArrayList,迭代过程其实就是数组的迭代。LinkedListLinkedHashSetLinkedHashMap迭代过程就是链表的迭代。这两者的迭代效率都很高,迭代时间与容器里的元素数目成正比。但HashSetHashMap迭代效率就略低了,因为采用了哈希表,所以元素是散列在数组中的,迭代时必须读完整个数组,迭代时间与容器的容量成正比。
  • Comparator:比较接口
    实现该接口后,集合内元素便可比较通过compare()方法实现元素排序
  • AbstractXXX:骨架类
    所谓骨架类,其实就是不同集合的核心代码实现,让继承这个抽象类的子类少干点活。例如AbstarctList代表“随机访问”集合(底层数组实现)的骨干代码实现。AbstractSequentialList代表“连续访问”(底层链表实现)集合的骨干代码实现。
  • Collections、Arrays
    集合工具类和数组工具类。Java中的工具类好像都喜欢在对应的接口或类名称后,加S来表示其工具类。

接下来给一张比较完整的util包框架图:

这里写图片描述

2. 常用集合类原理

2.1 ArrayList

ArrayList的实现最简单,采用的顺序表,底层就是一个Object数组,初始容量为10,每当元素要超过容量时,重新创建一个更大的数组,并把原数据拷到新数组中来。

2.2 LinkedList

LinkedList采用双向链表。集合中的每一个元素都会有两个成员变量prevnext,分别指向它的前一元素和后一元素。

ArrayListLinkedList的区别这里就不详细讨论了,其实就是顺序表和链表两种数据结构的区别。之前写的博文中已经提到(包括ArrayListLinkedList的详细实现):
数据结构基础(一)线性表

2.3 Vector

Vector底层实现和ArrayList类似,区别在于在许多方法上加了synchronized关键字,来实现了多线程安全。但代价是性能的降低。由于加锁的是整个集合,所以并发情况下进行迭代会锁住很长时间。

2.4 HashMap

HashMap采用的是哈希表结构,用链表法来解决hash冲突。这里不详细讨论,之前的文章写过:
HashMap原理解析

2.5 HashTable

HashTable的底层实现和HashMap类似,区别也是在许多方法上加了synchronized关键字,来实现了多线程安全。

2.6 LinkedHashMap

HashMap的基础上加了双链表,该集合中的每个元素也都保留了前一个元素和后一个元素的“指针”。这样便可以按照插入顺序来读取集合元素。也可设置为按照访问顺序来读取集合元素。
由于要维护额外的双链表,LinkedHashMap增删操作会比HashMap慢,但迭代时会比HashMap快。

2.7 TreeMap

采用了红黑树数据结构,从而实现了有序集合。这个比较复杂,以后单独开出一篇来讨论,此处略。

2.8 HashSet、LinkedHashSet、TreeSet

Set和Map有千丝万缕的联系呀。例如HashSet底层实现其实就是一个固定value的HashMap。LinkedHashSet就是一个value固定的LinkedHashMapTreeSet就是一个value固定的TreeMap

3. 集合的并发

3.1 并发类的选择

讲到并发的集合,一般都想到util包中的两个类:HashTableVector。然而实际使用情况中,并不推荐使用这两个类。

首先,HashTableVector是从JDK1.0便存在的“古老”类,当时CollectionMap接口都还没。这样导致的问题是,当后来HashTableVector实现MapCollection接口时,出现了许多无用而重复的方法。例如Vector原本有一个addElement()的方法,当实现了Collection接口后,又出现了一个add()方法。而实际上,这两个方法一模一样。

替代的这两个并发类的常见方法是Collections.synchronizedXXX(…),这个方法可以把ArrayListHashMap等集合变为线程安全的集合类。

那么,VectorCollections.synchronizedXXX(…)的底层实现有什么区别呢?

我们来看看两者的add()方法实现:

    //Vectorpublic synchronized boolean add(E e) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = e;return true;}//Collections.SynchronizedListpublic void add(int index, E element) {synchronized (mutex) {list.add(index, element);}}

可以看出, 两者实现多线程的方式都是对集合的方法加锁,区别在于,Vector是对方法加锁,锁的是本对象,而Collections.synchronizedXXX(…)是对一个变量加锁。区别并不大。

那么,既然Collections.synchronizedXXX(…)比较好,用它创建出线程安全的集合类是不是就一劳永逸的满足我们所有的需求了呢?很不幸,不完全是。

Collections.synchronizedXXX(…)HashTableVector在高并发时都有着很大的性能缺陷。因为它们的增、删、取都会锁住整个集合。想一想,一个线程在迭代十万个元素的Vector,其余线程对集合的操作时不时就阻塞了,受到了多大的影响啊。

为了解决这两种方法在高并发下的性能的低下。我们查找一下Java的API,发现在java.util.concurrent里面有许多针对高并发设计的类,例如:CopyOnWriteArrayListConcurrentHashMap

ConcurrentHashMap的优化原理在于,采用了Segment的机制:

这里写图片描述

可以看成,ConcurrentHashMap底层每一个Segment都是一个HashMap,这样增删取时只需要锁住一段的Segment,而不是整个集合。从而优化了高并发下的性能。

CopyOnWriteArrayList主要是对高并发下的读、迭代做优化。实现原理在于每次add,remove操作都是重新创建一个新的数组,等操作结束再把引用指向新的数组。add,remove都是加了锁的,而get方法没有加锁,因为每次迭代时都是在旧的数组上迭代。所以CopyOnWriteArrayList适用于读多写少的并发场景。

3.2 迭代fail-fast机制

之前写的博文:Java迭代foreach原理解析(java.util.ConcurrentModificationException的原因)


http://chatgpt.dhexx.cn/article/3pdPJp6g.shtml

相关文章

mysql-Util

将13位的时间戳字符串转换为4位的年的字符串 FROM_UNIXTIME(CONVERT(UPLOAD_TIME/1000 , signed),"%Y") 年结果: 将10位的时间戳字符串转换为4位的年的字符串 FROM_UNIXTIME(CONVERT(UPLOAD_TIME , signed),"%Y") 年结果: 根据A…

Util类简单介绍

集合简单介绍 一. Set集合 1.不包含重复元素、无序的元素集合 且存和取顺序不一致 无索引 2.Set集合的实现类有HashSet和LinkedHashSet Set接口继承于Collection接口 3.Set集合中没有get()方法 只有add(Element e)方法 没有add(key,Element)方法 4. 如:HashSet mySe…

史上最全总结!Util、POJO、domain、entity、model、DAO、DTO、view、mapper、service、controller的作用和区别分析

文章目录 前言工具类层Util 数据层POJO对象domainentitymodelviewDTO总结 数据访问层DAOmapper 业务层service 控制层Controller 前言 做开发项目时,总会遇到这些包,理清他们的层次,非常有助于我们对于项目的理解和建立。 现阶段CSDN上貌似…

vivado case_【vivado(3)】序列检测/状态机

手机上不好看可用电脑看 (1)首先建立一个工程名叫seq_det: 详细步骤可查看: 【vivado(1)】vivado软件的简单使用 【vivado(2)】计数器/testbench仿真 (2)建立一个design source如下所示: 右击design source, 选择add or create design source, 然后next 选择create file, …

vivado dcp生成

dcp与edif (write_edif命令生成) 比较: dcp主要有两个优点:第一个不需要手动生成stub文件,dcp是一个 压缩包里面包含所有文件。 第二个不需要xdc,尤其对于使用ip的设计。同时还可以使用加密功能。 不同阶段产生的dcp也不相同&a…

vivado ip打包归档

一般来说,要保存vivado工程使用的ip只需要xci文档即可。 但xci文档不仅仅是包含对应ip的配置信息,同样记录了一些path路径,以及ip核的属性(core container/ooc等) 使能core container后,将会以xcix方式保存ip核信息&…

Vivado驱动安装

一、卸载 二、打开Vivado 1 、 2 、 3、 4、 确认即可 5、安装证书 6、安装驱动 三、更新驱动程序

vivado2020.2导入原工程IP

vivado2020.2导入原工程IP 将原工程IP导入新工程中在新工程中添加每个IP的xci文件 将原工程IP导入新工程中 vivado 2022.2的IP在当前工程中.srcs中IP目录中,如下图: 将所需要转移的IP将完整的文件夹复制到新工程同样的目录中。 在新工程中添加每个IP的…

vivado 配置matlab,Matlab vivado

FPGA很多时候是用来做信号处理,而做信号处理都离不开Matlab。如通信中的调制解调、纠错码、各类编解码,这些都离不开Matlab,因为Matlab中simulink有非常丰富的库,方便客户建模和仿真。 以前modelsim 通过simulinx建模后&#xff0…

vivado使用方法

一、新建工程 首先打开vivado2017.4 点击create project 点击next 为新建的工程起名字,路径和名字都不要有中文 起好名字后点击next 起好名字后点击next 选择RTL project,勾选do not specify sources at this time,表示以后再配置资源文件 选…

【vivado UG学习】Synthesis策略学习

目录 1.1 综合方法1.2 使用Sythesis1.2.1 Sythesis设置1.2.2 创建运行策略1.2.3 控制文件编译顺序 1.2 运行Synthesis1.2.1 使用Tcl运行Synthesis1.2.2 RTL synthesis的多线程处理 参考文档 综合是将rtl指定的设计转换为门级表示的过程 1.1 综合方法 Vivado,可以&…

vivado filemgmt 20-2001

这个问题可能和vivado的打开路径有关,最好在工程路径下的shell中打开vivado在选择当前工程, 实测我遇到这个现象就是这个问题: 换到当前工程目录后:vivado在打开的位置都会生成一些log/jou文件等 参考: Xilinx Custo…

vivado 和 modesim 联合仿真快速修改重仿

vivado与modelsim的联合仿真(一)_坚持-CSDN博客_modelsim和vivado 1 编译联合仿真库 tool → compile_simulation_libraries ,选择simulator 为 modelsim simulator,填写好 compiled library location(联合库存放地址),simulator ex…

Vivado设置

1.本文部分素材来源网络,版权归原作者所有,如涉及作品版权问题,请与我联系删除; 2.未经原作者允许不得转载本文内容,否则将视为侵权; 3.转载或者引用本文内容请注明来源及原作者; 4.对于不遵…

vivado常见IP介绍

转自:微信公众号:Lauren的FPGA 目前,越来越多的工程师会用到Vivado IP Integrator(IPI)。它的强大之处在于通过实例化和互连IP构建复杂的设计。现在的IPI中,不仅可以添加Vivado IP,还可以添加用…

vivado工程打包

一般使用自带archive功能进行归档,但是归档的工程路径较乱,不能将源文件和工程进行明显的分析。一种比较常用的方法就是使用tcl脚本: 现在已经有了生成的语法模板,需要在修改下自己需要的新工程名称,并去掉一些不需要的…

使用vivado封装IP

文章目录 Basics定制IP的参数Enablement Expression封装IP时使用了绝对路径封装IP时设置Address Map Addr相关tcl修正警告Bus Interface clk: ASSOCIATED_BUSIF bus parameter is missing.rst识别成低有效复位Bus Interface up_axi: FREQ_HZ bus parameter missing from AXI in…

vivado使用方法(初级)

文章目录 1 创建新工程1.1 工程创建1.2 新建Verilog文件1.3 仿真 参考 1 创建新工程 1.1 工程创建 1、首先打开Vavido软件,点击Creat Project或者在File——>Project——>New里面进行新工程的创建 2、然后在弹出的界面上点击Next进入下一个界面进行项目的命…

Vivado基础教程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、创建项目二、添加设计文件代码 三、综合四、添加约束文件五、上板5.1、生产比特流文件5.2、硬件调试 前言 本文详细的讲述了vivado项目创建到上板的流程。…