Java集合 总结篇(全)

Java集合

img

集合底层框架总结

List

代表的有序,可重复的集合。

  • ArrayList -- 数组 -- 把他想象成C++中的Vector就可以,当数组空间不够的时候,会自动扩容。 -- 线程不安全

  • LinkedList -- 双向链表 -- 可以将他理解成一个链表,不支持随机存取,但是增加删除特别方便。

  • Vector -- 数组 -- 线程安全

comparable Comparator 的区别

comparable 是Java中的一个接口,定义在lang包下,他的比较方法是comparableTo。他是一个Java 中内置的比较方法,不是独立的。例如我可以根据年龄,来为对象排序。这个comparableTo 是写在类之中的。

class Person implements Comparable<Person> {private String name;private int age;
​public Person(String name, int age) {this.name = name;this.age = age;}
​// Implementing compareTo method of Comparable interface@Overridepublic int compareTo(Person otherPerson) {return Integer.compare(this.age, otherPerson.age);}
}
​
public class Main {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));
​Collections.sort(people);
​for (Person person : people) {System.out.println(person);}}
}

Comparator 是一个独立的接口,定义在Util 包下。他如果对对象进行排序,需要重写 compare 方法,然后在外部对具体如何排序进行书写,也正因为写在外部,所以可以有多种排序方式,与之相反的Compareable 接口由于在类内部,所以只有一种排序方式,不可改变。

class Person implements Comparable<Person> {private String name;private int age;
​public Person(String name, int age) {this.name = name;this.age = age;}
​// Implementing compareTo method of Comparable interface@Overridepublic int compareTo(Person otherPerson) {return Integer.compare(this.age, otherPerson.age);}
​// Getter methods for name and agepublic String getName() {return name;}
​public int getAge() {return age;}
​// toString method for printing Person objects@Overridepublic String toString() {return name + " - " + age;}
}
​
public class Main {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));
​Collections.sort(people);
​for (Person person : people) {System.out.println(person);}}
}

ArrayList如何序列化

transient 修饰 存储元素的elementData,目的是不让被修饰的成员属性序列化。

那为什么不可以直接序列化 ArrayList?

因为ArrayList的空间可能是100,但是只有60个有元素,那么就极大的浪费空间,且效率低下。

如何序列化

通过的是readObject和writeObject方法,实际使用的是流的方式。

ObjectOutputStreamObjectInputStream来进行序列化和反序列化。

ArrayList的扩容机制

首先,我们在创建ArrayList时,我们可以指定ArrayList的初始容量,但随着add()方法,不断往ArrayList添加元素,这个时候ArrayList的容量满了,我们需要对 ArrayList 进行扩容。

流程为:创建了一个当前数组容量*1.5大小的 ArrayList,然后将原来的数组中的元素利用Arrays.copyOf() 方法放入 新数组中。再将准备新加入的元素加入新数组中。

图示:

堆栈过程图示:
add(element)
└── if (size == elementData.length) // 判断是否需要扩容├── grow(minCapacity) // 扩容│   └── newCapacity = oldCapacity + (oldCapacity >> 1) // 计算新的数组容量│   └── Arrays.copyOf(elementData, newCapacity) // 创建新的数组├── elementData[size++] = element; // 添加新元素└── return true; // 添加成功
​
LinkedList 为什么不能实现RandomAccess接口

RandomAccess 是一个标记接口,用来表明实现该接口的类支持随机访问(即可以通过索引快速访问元素)。由于 LinkedList 底层数据结构是链表,内存地址不连续,只能通过指针来定位,不支持随机快速访问,所以不能实现 RandomAccess 接口。

Queue

  • PriorityQueue -- 数组来实现二叉堆

  • ArrayQueue -- 数组 + 双指针

Set

代表的有序,不可重复的集合。

  • HashSet(无序,唯一) -- 基于 HashMap 实现,底层是哈希表

  • LinkedHashSet(HashSet的子类,有序) -- 基于LinkedHashMap实现,底层是链表 + 哈希表

  • TreeSet (有序,唯一)-- 红黑树

Map

以键值对方式存储。代表的是键值对的集合。

  • HashMap -- JDK1.8 前:数组+链表。JDK1.8后:如果链表阈值大于默认值(8),会将链表转换为红黑树,但转换前会先判断数组大小是否小于64,如果小于的话,优先数组扩容。总结:数组+链表或红黑树。

  • LinkHashMap -- 数组+链表或红黑树。不同的是,在HashMap基础上,增加了一条双向链表,可以保证顺序与插入顺序一致。

  • TreeMap -- 红黑树。 因为TreeMap还实现了 SortedMap 和 NavigableMap 接口,所以会比 HashMap 多了搜寻和排序的功能。可以自定义排序规则。

HashMap详解

数据结构:

HashMap -- JDK1.8 前:数组+链表。JDK1.8后:如果链表阈值大于默认值(8),会将链表转换为红黑树,但转换前会先判断数组大小是否小于64,如果小于的话,优先数组扩容。总结:数组+链表或红黑树。使用了拉链法来解决的哈希冲突。

JDK1.8 前:

JDK1.8后:

线程安全:

非线程安全,但是HashTable是线程安全的。因为HashTable中的方法基本上都经过 synchronized 修饰过的。

初始容量和扩容机制:

HashMap如果未指定初始大小,那么默认初始容量大小是16,且每次扩容都是之前的二倍。如果给定初始容量大小 n,那么容量为给定大小的2 的n次幂。

而HashTable 如果未指定初始大小,那么默认初始容量大小是11,且每次扩容都是之前的 2n + 1 。如果指定初始容量大小,那么容量直接就是给定的大小。

为什么 HashMap 的⻓度为什么是 2 的幂次方

因为 Hash 值范围非常大,但是空间是不能容得下这么多哈希值的,所以需要 Hash值 数组长度进行取模运算。也就是 Hash % length ,但是这个这个值是与 Hash & (length - 1 )是相等的。

举个例子如果 数组长度是 16,hash值是 10101 ,hash & (ength - 1) = 10101 & 1111。这样可以看到 hash 值的后四位就可以被用来计算数组的索引。

  1. 会方便计算,也可以使其分布更加均匀。(因为与 hash 值有关)。

  2. 并且如果数组长度是2 的幂次方,就可以用 与运算。也会使效率更高。

如果初始化一个HashMap长度为17,还是会变成 32 容量。

HashMap 的 put 流程

三分恶面渣逆袭:HashMap插入数据流程图

先利用 hashcode 获取哈希值,然后根据哈希值和数组长度算出键值对在数组中的索引。如果当前数组的桶为空,直接添加。如果不为空,判断key 相同与否,如果相同,则覆盖,不相同的话遍历链表或者遍历树。在链表中,如果 key 相同,则覆盖,如果key 不存在,添加进链表中,作为尾节点,并判断如果超过链表阈值,则转换为红黑树。

HashMap的查询,删除的时间复杂度

HashMap可以直接根据哈希码来确认数组下标,所以查询和删除的时间复杂度都是 o(1) 。但是如果发生哈希冲突的话,链表还未转换成红黑树,时间复杂度就变成了o(n),n是链表长度,如果转变成了红黑树,时间复杂度变成了 o(logn).

ConcurrentHashMap

从上文已知,HashMap 是线程不安全的,那如果我们想用线程安全的哈希表,就可以用 ConcurrentHashMap。

在Jdk 1.8 之前,ConcurrentHashMap 的底层数据结构是 分段数组 + 链表的形式。每个分段可以独立锁定,当需要读取数据的时候,不需要锁震整个数组,只需要锁定当前数据所在的段的段就可以。可以提高并发的性能。当一个线程锁上一个数据段的时候,其他的数据段仍然可以被另外的线程读取。 如果有些方法需要跨段,那么就可以按顺序锁住所有的段,然后再按顺序释放就可以。

Segment 数组中的每个元素包含⼀个 HashEntry 数组,每个 HashEntry 数组属于链表结构。

这样就可以保证线程安全。

JDK1.8之后,ConcurrentHashMap 取消了 Segment 分段数组,只保留了一大个数组,也就是 table 数组。取而代之,保证线程安全用的是CAS 和 synchronized 锁,避免不必要的锁的开销。另一个变化是像HashMap一样增加了红黑树,防止链表长度过长。

JDK 1.8 最大并发数是Node数组的大小,而Jdk1.7并发数是 Segment 的数量。

ConcurrentHashMap 和 HashTable 的区别

首先,他们俩都是线程安全的,但是数据结构不同。

HashTable 的数据结构利用了 数组加链表,ConcurrentHashMap 的数据结构参考上文。

其次,实现线程安全的方式也不同,HashTable使⽤ synchronized 来保证线程安全,同一时段,只能一个线程访问,效率低下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/321703.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

广州工业冷风机在通风降温的优点

工业冷风机在通风降温方面具有一些显著的优点&#xff0c;以下是对其优点的分析&#xff1a; 优点&#xff1a; 高效降温&#xff1a;工业冷风机采用水蒸发原理&#xff0c;通过将热空气经过湿帘或水幕冷却&#xff0c;迅速降低空气温度&#xff0c;具有高效降温的特点。成本…

DCEP数字人民币:中国法定区块链中数字货币

一、背景 作为全球第二大经济体&#xff0c;中国在数字货币领域的发展一直备受关注。近年来&#xff0c;中国政府积极推动数字货币的研究和试点工作&#xff0c;逐步开放数字货币交易试点&#xff0c;并计划推出中国唯一合法数字货币——数字人民币&#xff08;RMB Coin&#…

47.Redis学习笔记

小林coding -> 图解redis的学习笔记 文章目录 Rediswindwos安装docker安装redis启动redis使用RDM访问虚拟机中的redispython连接redis缓存穿透、击穿、雪崩基本数据类型高级数据类型高并发指标布隆过滤器分布式锁Redis 的有序集合底层为什么要用跳表&#xff0c;而不用平衡…

AI预警未来:山体滑坡与塌方事故的潜在发现者

在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;的应用已经渗透到了我们生活的各个领域。而在防灾减灾的领域中&#xff0c;AI技术的引入无疑为我们打开了一扇新的大门。以梅大高速大埔往福建方向K11900m附近发生的路面塌方灾害为例&#xff0c;我们不禁思…

C++ | Leetcode C++题解之第74题搜索二维矩阵

题目&#xff1a; 题解&#xff1a; class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int m matrix.size(), n matrix[0].size();int low 0, high m * n - 1;while (low < high) {int mid (high - low) / 2 l…

UART、TIMER

UART简介&#xff08;通用异步收发器&#xff0c;通常称串口&#xff09; UART&#xff0c;是一种串行、异步、全双工的通信协议&#xff0c;在嵌入式领域应用的非常广泛。 UART作为异步串行通信协议的一种&#xff0c;工作原理是将传输数据的每个二进制位一位接一位地传输。…

五一 大项目

Docker 中的 Nginx 服务为什么要启用 HTTPS 一安装容器 1 安装docker-20.10.17 2 安装所需的依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm23 添加Docker官方仓库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos…

言出身随!人情世故:利益交换与人脉的重要性——早读(逆天打工人爬取热门微信文章解读)

巴黎输了&#xff0c;看了比赛还得加班 引言Python 代码第一篇 洞见 认知越高的人&#xff0c;越懂得感恩第二篇 冯站长之家 2024年5月8日&#xff08;周三&#xff09;三分钟新闻早餐结尾 智慧赋予我决策的明灯 勇气则是我行动的盾牌 在细雨中骑行 是我以智慧选择的道路 用勇气…

富唯智能复合机器人:CNC铝块上下料安全新标准

在CNC铝块加工过程中&#xff0c;上下料环节的安全问题一直是企业关注的焦点。富唯智能复合机器人的应用&#xff0c;为这一环节树立了新的安全标准。 传统的上下料方式往往依赖于人工操作&#xff0c;存在着较大的安全隐患。而富唯智能复合机器人采用先进的视觉识别技术和精准…

前端如何设置div可滚动,且设置滚动条颜色

在前端中&#xff0c;设置 div 为可滚动并通过 CSS 自定义滚动条的颜色并不是所有浏览器都直接支持的功能&#xff0c;因为滚动条的样式在很大程度上取决于操作系统和浏览器的默认样式。然而&#xff0c;你可以使用某些 CSS 属性来尝试自定义滚动条的外观&#xff0c;这些属性在…

一分钟教你学浪app视频怎么缓存

你是否在学浪app上苦苦寻找如何缓存视频的方法&#xff1f;你是否想快速、轻松地观看自己喜欢的视频内容&#xff1f;那么&#xff0c;让我们一起探索一分钟教你如何缓存学浪app视频的技巧吧&#xff01; 学浪下载工具我已经打包好了&#xff0c;有需要的自己下载一下 学浪下…

OpenAI的搜索引擎要来了!

最近的报道和业界泄露信息显示&#xff0c;OpenAI正秘密研发一款新的搜索引擎&#xff0c;可能叫SearchGPT或Sonic&#xff0c;目标是挑战Google的搜索霸权。预计这款搜索引擎可能在5月9日即将到来的活动中正式亮相。 SearchGPT的蛛丝马迹 尽管OpenAI对SearchGPT尚未表态&…

如何在Hostease的Linux虚拟主机上永久移除WordPress网站

最近有遇到客户咨询如何移除Linux虚拟主机上的WordPress网站的&#xff0c; 因为原先的站点长时间不更新&#xff0c;被恶意篡改&#xff0c;跳转到了一个博彩网站上&#xff0c;本身网站也比较旧了&#xff0c;客户也不准备修复&#xff0c;准备重新建站。但是又怕移除不干净&…

合并两个有序数组题目讲解

一&#xff1a;题目 非递减顺序可以理解为&#xff1a;不完全递增顺序&#xff0c;它不是完全的递增&#xff0c;会存在前后相等的情况&#xff0c;比如 [1&#xff0c;2&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;6] &#xff0c;这就是非递减顺序。 二&#xff1…

3. 分布式链路追踪的链路日志设计

前言 分布式链路追踪的客户端实现中&#xff0c;我们会通过各种手段和规则得到一个又一个的Span&#xff0c;得到这些Span后&#xff0c;需要在分布式链路追踪的服务端这边汇总这些Span并拼接出一条请求链路&#xff0c;那么这里就存在一个问题&#xff0c;客户端得到的Span如…

vue脚手架和vite创建的项目的环境配置

开发环境文件 .env.development NODE_ENV"development" # // 开发接口域名 本地测试就用这个 # vue脚手架创建的 VUE_APP_MODE"开发环境" VUE_APP_API_URL http://19527 # vite创建的 # VITE_MODE"开发环境" # VITE_BASE_URL http://1920:9527…

【自动驾驶|毫米波雷达】初识毫米波雷达射频前端硬件

第一次更新&#xff1a;2024/5/4 目录 整体概述 混频器&#xff08;MIXER&#xff09; 低通滤波器&#xff08;LPF&#xff1a;Low-Pass filter&#xff09; 数模转换器&#xff08;ADC&#xff1a;Analog to Digital Converter&#xff09; 毫米波雷达功能框图 整体概述 完…

开源go实现的iot物联网新基建平台

软件介绍 Magistrala IoT平台是由Abstract Machines公司开发的创新基础设施解决方案&#xff0c;旨在帮助组织和开发者构建安全、可扩展和创新的物联网应用程序。曾经被称为Mainflux的平台&#xff0c;现在已经开源&#xff0c;并在国际物联网领域受到广泛关注。 功能描述 多协…

如何利用AI提高内容生产效率

一&#xff1a;简介 通过AI技术可以在内容生产过程中提升效率和质量&#xff0c;以下是一些方法和应用场景&#xff1a; 1. 自动化内容生成&#xff1a; 自然语言生成&#xff08;NLG&#xff09;&#xff1a;通过AI技术&#xff0c;可以自动生成文章、报告、产品描述等文…

原型模式类图与代码

现要求实现一个能够自动生成求职简历的程序&#xff0c;简历的基本内容包括求职者的姓名、性别、年龄及工作经历。希望每份简历中的工作经历有所不同&#xff0c;并尽量减少程序中的重复代码。 采用原型模式(Prototype)来实现上述要求&#xff0c;得到如图 7.25 所示的类图。 原…