史上最全的Java集合类解析

06_java常见集合类底层实现 List、Set、Map常见集合接口实现类源码学习 阅读详情
本文仅分析部分原理和集合类的特点,不分析源码,旨在对java的集合类有一个整体的认识,理解各个不同类的关联和区别,让大家在不同的环境下学会选择不同的类来处理。

Java中的集合类包含的内容很多而且很重要,很多数据的存储和处理(排序,去重,筛选等)都需要通过集合类来完成。


首先java中集合类主要有两大分支:

(1)Collection (2)Map

先看它们的类图:

(1)Collection

Collection

(2)Map
Map

可以看到它们之间的关系纷繁复杂,如果不系统的学习一下,还真是不知道有什么区别,该怎么选择。由于HashSet的内部实现原理是使用了HashMap,所以我们的学习路线为先学习Map集合类,然后再来学习Collection集合类。


(1)HashMap和Hashtable ( 注意table是小写的t,搞不懂为什么要这样,老是会写错。。。)

首先来看HashMap和HashTable,这两兄弟经常被放到一起来比较,那么它们有什么不一样呢?

a.HashMap不是线程安全的;HashTable是线程安全的,其线程安全是通过Sychronize实现。

b.由于上述原因,HashMap效率高于HashTable。

c.HashMap的键可以为null,HashTable不可以。

d.多线程环境下,通常也不是用HashTable,因为效率低。HashMap配合Collections工具类使用实现线程安全。同时还有ConcurrentHashMap可以选择,该类的线程安全是通过Lock的方式实现的,所以效率高于Hashtable。

好,比较了他们的不一样后,来讲讲它们的原理。

数组,链表,哈希表。各有优劣,顺便提一下,数组连续内存空间,查找速度快,增删慢;链表充分利用了内存,存储空间是不连续的,首尾存储上下一个节点的信息,所以寻址麻烦,查找速度慢,但是增删快;哈希表呢,综合了它们两个的有点,一个哈希表,由数组和链表组成。假设一条链表有1000个节点,现在查找最后一个节点,就得从第一个遍历到最后一个;如果用哈希表,将这条链表分为10组,用一个容量为10数组来存储这10组链表的头结点(a[0] = 0 , a[1] = 100 , a[2] = 200 …)。这样寻址就快了。

HashMap实现原理就是上述原理了,当然其具体实现还有很多其他的东西。Hashtable同理,只不过做了同步处理。

Hash碰撞,不同的key根据hash算法算出的值可能一样,如果一样就是所谓的碰撞。

优化措施:

(1) HashMap的扩容代价非常大,要生成一个新的桶数组,然后要把所有元素都重新Hash落桶一次,几乎等于重新执行了一次所有元素的put。所以如果我们对Map的大小有一个范围的话,可以在构造时给定大小,一般大小设置为:(int) ((float) expectedSize / 0.75F + 1.0F)。

(2) key的设计尽量简洁。


HashMap一些功能实现:

a.按值排序

HashMap按值排序通过Collections的sort方法,在实现排序之前,我们先看看HashMap的几种遍历方式:

	//Collection And Map
	public static void testCM(){
		//Collection
		Map<Integer , String> hs = new HashMap<Integer , String>();
		int i = 0;
		hs.put(199, "序号:"+201);
		while(i<50){
			hs.put(i, "序号:"+i);
			i++;
		}
		hs.put(-1, "序号:"+200);
		hs.put(200, "序号:"+200);
		
		//遍历方式一:for each遍历HashMap的entryset,注意这种方式在定义的时候就必须写成
		//Map<Integer , String> hs,不能写成Map hs;
		for(Entry<Integer , String> entry : hs.entrySet()){
			System.out.println("key:"+entry.getKey()+"  value:"+entry.getValue());
		}
		//遍历方式二:使用EntrySet的Iterator
		Iterator<Map.Entry<Integer , String>> iterator = hs.entrySet().iterator();
		while(iterator.hasNext()){
			Entry<Integer , String> entry =  iterator.next();
			System.out.println("key:"+entry.getKey()+"  value:"+entry.getValue());
		};
		//遍历方式三:for each直接使用HashMap的keyset
		for(Integer key : hs.keySet()){
			System.out.println("key:"+key+"  value:"+hs.get(key));
		};
		//遍历方式四:使用keyset的Iterator
		Iterator keyIterator = hs.keySet().iterator();
		while(keyIterator.hasNext()){
			Integer key = (Integer)keyIterator.next();
			System.out.println("key:"+key+"  value:"+hs.get(key));
		}	
	}
(1)使用keyset的两种方式都会遍历两次,所以效率没有使用EntrySet高。
(2)HashMap输出是无序的,这个无序不是说每次遍历的结果顺序不一样,而是说与插入顺序不一样。

接下来我们看按值排序,注释比较详细就不赘述过程了。

	//对HashMap排序
	public static void sortHashMap(Map<Integer , String> hashmap){
		
		System.out.println("排序后");
		
		//第一步,用HashMap构造一个LinkedList
		Set<Entry<Integer , String>> sets = hashmap.entrySet();
		LinkedList<Entry<Integer , String>> linkedList = new LinkedList<Entry<Integer , String>>(sets);
		
		//用Collections的sort方法排序
		Collections.sort(linkedList , new Comparator<Entry<Integer , String>>(){

			@Override
			public int compare(Entry<Integer , String> o1, Entry<Integer , String> o2) {
				// TODO Auto-generated method stub
				/*String object1 = (String) o1.getValue();
				String object2 = (String) o2.getValue();
				return object1.compareTo(object2);*/
				return o1.getValue().compareTo(o2.getValue());
			}
			
		});
		
		//第三步,将排序后的list赋值给LinkedHashMap
		Map<Integer , String> map = new LinkedHashMap();
		for(Entry<Integer , String> entry : linkedList){
			map.put(entry.getKey(), entry.getValue());
		}
		for(Entry<Integer , String> entry : map.entrySet()){
			System.out.println("key:"+entry.getKey()+"  value:"+entry.getValue());
		}
	}

b.按键排序

HashMap按键排序要比按值排序方法容易实现,而且方法很多,下面一一介绍。

第一种:还是熟悉的配方还是熟悉的味道,用Collections的sort方法,只是更改一下比较规则。

第二种:TreeMap是按键排序的,默认升序,所以可以通过TreeMap来实现。

	public static void sortHashMapByKey(Map hashmap){
		
		System.out.println("按键排序后");
		
		//第一步:先创建一个TreeMap实例,构造函数传入一个Comparator对象。
		TreeMap<Integer , String> treemap = new TreeMap<Integer , String>(new Comparator<Integer>(){

			@Override
			public int compare(Integer o1,Integer o2) {
				// TODO Auto-generated method stub
				return Integer.compare(o1, o2);
			}
			
		});
		//第二步:将要排序的HashMap添加到我们构造的TreeMap中。
		treemap.putAll(hashmap);
		for(Entry<Integer , String> entry : treemap.entrySet()){
			System.out.println("key:"+entry.getKey()+"  value:"+entry.getValue());
		}
	}

第三种:可以通过keyset取出所有的key,然后将key排序,再有序的将key-value键值对存到LinkedHashMap中,这个就不贴代码了,有兴趣的可以自己去尝试一下。

c.value去重

对于HashMap而言,它的key是不能重复的,但是它的value是可以重复的,有的时候我们要将重复的部分剔除掉。

方法一:将HashMap的key-value对调,然后赋值给一个新的HashMap,由于key的不可重复性,此时就将重复值去掉了。最后将新得到的HashMap的key-value再对调一次即可。

d.HashMap线程同步

第一种:

Map<Integer , String> hs = new HashMap<Integer , String>();
		hs = Collections.synchronizedMap(hs);

第二种:

ConcurrentHashMap<Integer , String> hs = new ConcurrentHashMap<Integer , String>();

(2)IdentifyHashMap

IdentityHashMap与HashMap基本相似,只是当两个key严格相等时,即key1==key2时,它才认为两个key是相等的 。IdentityHashMap也允许使用null,但不保证键值对之间的顺序。


(3)WeakHashMap

WeakHashMap与HashMap的用法基本相同,区别在于:后者的key保留对象的强引用,即只要HashMap对象不被销毁,其对象所有key所引用的对象不会被垃圾回收,HashMap也不会自动删除这些key所对应的键值对对象。但WeakHashMap的key所引用的对象没有被其他强引用变量所引用,则这些key所引用的对象可能被回收。WeakHashMap中的每个key对象保存了实际对象的弱引用,当回收了该key所对应的实际对象后,WeakHashMap会自动删除该key所对应的键值对。


接下来是Collection接口及其子类:

(4)ArrayList , LinkedList , Vector

(1)首先,说说它们的关系和区别。ArrayList和Vector本质都是用数组实现的,而LinkList是用双链表实现的;所以,Arraylist和Vector在查找效率上比较高,增删效率比较低;LinkedList则正好相反。ArrayList是线程不安全的,Vector是线程安全的,效率肯定没有ArrayList高了。实际中一般也不怎么用Vector,可以自己做线程同步,也可以用Collections配合ArrayList实现线程同步。

(2)Tips

前面多次提到扩容的代价很高,所以如果能确定容量的大致范围就可以在创建实例的时候指定,注意,这个仅限于ArrayList和Vector哟:

ArrayList arrayList = new ArrayList(100);
arrayList.ensureCapacity(200);
Vector vector = new Vector(100);
vector.ensureCapacity(200);

(3)其他功能实现

a.排序

List的排序的话就是使用Collections的sort方法,构造Comparator或者让List中的对象实现Comparaable都可以,这里就不贴代码了。

b.去重

第一种:用Iterator遍历,遍历出来的放到一个临时List中,放之前用contains判断一下。

第二种:利用set的不可重复性,只需三步走。

//第一步:用HashSet的特性去重
	HashSet tempSet = new HashSet(arrayList);
    //第二步:将arrayList清除
	tempSet.clear();
	//第三步:将去重后的重新赋给List
	arrayList.addAll(tempSet);

(5)Stack

Stack呢,是继承自Vector的,所以用法啊,线程安全什么的跟Vector都差不多,只是有几个地方需要注意:

第一:add()和push(),stack是将最后一个element作为栈顶的,所以这两个方法对stack而言是没什么区别的,但是,它们的返回值不一样,add()返回boolean,就是添加成功了没有;push()返回的是你添加的元素。为了可读性以及将它跟栈有一丢丢联系,推荐使用push。

第二:peek()和pop(),这两个方法都能得到栈顶元素,区别是peek()只是读取,对原栈没有什么影响;pop(),从字面上就能理解,出栈,所以原栈的栈顶元素就没了。


(6)HashSet和TreeSet

Set集合类的特点就是可以去重,它们的内部实现都是基于Map的,用的是Map的key,所以知道为什么可以去重复了吧。
既然要去重,那么久需要比较,既然要比较,那么久需要了解怎么比较的,不然它将1等于2了,你怎么办?

比较是基于hascode()方法和equals()方法的,所以必要情况下需要重新这两个方法。


好了,到了总结的时候了,其实你会发现集合类虽然看起来多,但是都是很有规律的。HashSet,TreeSet一个无序,一个有序;HashMap,LinkedHasmMap,一个无序,一个有序;Vector和HashTable,Stack是线程安全的,但是效率低;线程不安全的类都可以配合Collections得到线程安全的类。
深入解析Java中的Vector集合类! 在Java开发中,集合类是非常常用的数据结构。在这些集合类中,Vector是一个非常有用的类,可以在需要动态添加或者删除元素的时候快速操作数据。本文将会对Java中的Vector集合类进行深入解析。首先,我们将会介绍Vector的概述和源代码解析。然后,我们将会通过一个应用场景案例来展示Vector的使用方法。接着,我们会对Vector的优缺点进行分析。最后,我们将会介绍类代码方法和测试用例,并对全文进行小结和总结。Vector是Java的一个集合类,它是线程安全的。 阅读详情

相关推荐

Vector集合类解析

在Java开发中,集合类是非常常用的数据结构。在这些集合类中,Vector是一个非常有用的类,可以在需要动态添加或者删除元素的时候快速操作数据。本文将会对Java中的Vector集合类进行深入解析。首先,我们将会介绍Vector的概述和源代码解析。然后,我们将会通过一个应用场景案例来展示Vector的使用方法。接着,我们会对Vector的优缺点进行分析。最后,我们将会介绍类代码方法和测试用例,并对全文进行小结和总结。Vector是Java的一个集合类,它是线程安全的。

**My Coding Family** 1197

WeakHashMap

WeakHashMap:键是weak引用。

xiaoxishuaidaile的博客 1532

Java集合类框架矩阵图解析

Java集合框架(Java Collections Framework)是一组接口和类,用于在Java程序中存储和操作数据集合。集合框架为Java开发者提供了一套统一的数据操作标准,简化了数据存储结构的操作过程。这一框架的存在,使得处理复杂数据集合变得更为高效和安全。在Java集合框架中,接口是定义了一组方法的契约,这些方法可以被不同的类实现。接口中的方法都是抽象的,意味着它们只声明了方法的签名而没有具体实现。

weixin_42376614的博客 1055

辨析:HashMap、HashTable、ConcurrentHashMap、WeakHashMap、LinkedHashMap

第二部分:HashMap之大局观--辨析 一、概述Map种类 Java 自带了各种 Map 类。这些 Map 类可归为三种类型: 通用 Map,用于在应用程序中管理映射,通常在 java.util 程序包中实现 HashMap(非线程安全,强引用) Hashtable(线程安全) Properties(线程安全) LinkedHashMap(保存查询插入顺序) IdentityHashMap(key可重,非线程安全) TreeMap(排序) WeakHashMap...

qq_44641527的博客 1022

微信小程序真机HTTPS证书链失效排查与修复指南

HTTPS证书信任链是保障Web通信安全的基础机制,其核心在于客户端能否通过服务器提供的证书及其上级签发者,逐级回溯至自身预置的可信根证书。在微信小程序场景中,由于客户端不复用系统根证书库,而是采用固化、精简且更新滞后的自研CA白名单,导致大量符合浏览器标准的证书(如Let’s Encrypt新版ISRG Root X1、TrustAsia等)在真机环境下触发net::ERR_CERT_AUTHORITY_INVALID错误。该问题本质是证书链断裂或签名算法/密钥长度不合规,而非域名配置或CORS策略异常。

weixin_33935636的博客 676

HFSS学习记录——0. HFSS软件安装(ANSYS Electromagnetics Suite 2023 R1)

HFSS 2023 R1安装步骤

plmxu34的博客 15万+

Java集合类解析

最近看了下Java中的集合类对象,发现零碎的知识好多,有些记忆已经模糊了,突然想回忆下这块内容,给自己充充电。废话少说了,直接入主题吧~~ 在Java中有一套设计优良的接口和类组成了Java集合框架,使程序员操作成批的数据或对象元素极为方便。所有的Java集合都在java.util包中。网上找了一张图片详细解释了其中的关系: 然后看出集合之间的(继承)关系,还是文字说下比较直观点,以下是常用的集

superMrLiu的博客 518

Oracle迁移至华为GaussDB SQL语法和存储过程转换

在将Oracle数据库迁移至GaussDB时,SQL语法和存储过程的转换是确保应用程序正常运行和数据完整性的关键环节。由于两者在数据类型、函数、过程语言等方面存在差异,必须系统化地进行转换和测试。正则表达式脚本:批量替换常见的语法差异。SQL解析工具:解析SQL脚本,生成GaussDB兼容的语法。代码审查工具:自动检查转换后的代码,确保语法和逻辑正确。将Oracle迁移至GaussDB涉及到SQL语法和存储过程的全面转换。通过系统化的转换步骤、使用合适的工具并结合手动调整,可以确保迁移过程的顺利进行。

weixin_38428874的博客 2395

java hashmap putall_java – 使用LinkedHashMap.putAll()插入元素的顺序是什么?

本段适用于使用the special constructor创建的地图,该地图根据上次访问顺序(相对于标准LinkedHashMap的插入顺序)生成迭代顺序.它只是说如果一个键K在地图中,你调用putAll(someOtherMap),其中someOtherMap也包含K,这将被视为对K的访问,它将被移动到地图的末尾(来自迭代顺序)透视).换句话说,从访问角度来看,putAll等同于(条目e:条目...

weixin_33506900的博客 1012

TIBCO Spotfire 入门指南

数据分析工具 - TIBCO Spotfire 入门指南(一) 文章目录数据分析工具 - TIBCO Spotfire 入门指南(一)前言一、Sportfire 是什么?二、使用Sportfire 创建一个简单的数据分析模型1.设置分析(加载数据)2.编辑数据源3.创建图表3.1 创建交叉表3.2 创建饼图3.3 创建树形图3.4 创建散点图3.5 创建自定义筛选器总结 前言 通过对本指南的学习,你可以了解到如何开始用TIBCO Sportfire分析数据,并能详细了解您可以做什么以及怎么做 一、Spo

kaiakai111的博客 1万+

蓝牙学习笔记之HCI协议(一)

目录 协议浅述 HCI简介 HCI协议数据格式 HCI Command Packet HCI ACL Data Packet HCI Synchronous(SCO) Data Packet HCI Event Packet HCI命令和事件介绍 Inquiry command Write Local Name Command Read BD_ADDR Command H...

在云巅的博客 2万+

JAVA中集合类概述

这篇文章是根据张席主编的《JAVA语言程序设计教程》提炼出来的一些JAVA中集合的知识,还会加上我在编程过程中的遇到的问题和使用心得,如有错误欢迎指正。JAVA中的集合类可以分为两大类: 一类是实现Collection接口;另一类是实现Map接口。Collection是一个基本的集合接口,Collection中可以容纳一组集合元素(Element)。Map没有继承Collection接口,与Collection是并列关系。Map提供键(Key)到值(Value)的映射。

weixin_62438655的博客 4457

从 VS Code 登录 ABAP Destination,一次把前后端连接跑通

最近很多 ABAP 开发者开始把 VS Code 纳入日常开发环境,原因很直接,VS Code 的轻量体验、命令面板、文件树、插件生态和 AI 编程能力,已经深深影响了现代开发者的工作方式。SAP 官方发布的 ABAP Development Tools for VS Code,也把 ABAP Cloud 开发模型带进了这个编辑器里。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 220

java集合原理_史上最全的Java集合类解析

本文仅分析部分原理和集合类的特点,不分析源码,旨在对java的集合类有一个整体的认识,理解各个不同类的关联和区别,让大家在不同的环境下学会选择不同的类来处理。Java中的集合类包含的内容很多而且很重要,很多数据的存储和处理(排序,去重,筛选等)都需要通过集合类来完成。首先java中集合类主要有两大分支:(1)Collection (2)Map先看它们的类图:(1)Collection(2)Map可...

weixin_29477915的博客 236

基于STM32L4XX 、HAL库的TMP144YFFR数字温度传感器驱动应用C语言程序设计

define TMP144_ADDRESS 0x00 // 默认为全局地址,用于单器件或MDA命令。#define TMP144_CMD_READ_TEMP 0x00 // 读取温度寄存器命令。if (temp_raw & 0x800) { // 判断第11位(符号位)

PP_Cottage的博客 91

国产系统(统信 UOS )漏洞修复方式

2.1 服务器版(单漏洞更新):服务器标准版:yum upgrade-minimal --cve “CVE编号”服务器 D 版:sudo apt update&&sudo apt install “受影响的软件包”1 统信 UOS 漏洞修复方式在线升级修复桌面专业版:通过以下步骤打开在线升级:控制中心–>更新–>更新设置–>打开系统更新、安全更新。安装过程中,请勾选“我已阅读并知晓”,然后点击“开始升级”。2 点击“检查更新”–“全部下载”,如果不想进行系统更新,可以选择只下载“安全更新”。

Reyn_观极 5007

Java集合类详解

Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHashMap Collection接口   Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Element

毛凡的博客 17万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

一文搞定Java集合类,你还在为Java集合类而烦恼吗?

常用集合类

轻松玩编程 1188

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Java 中的集合类:深入解析与分类

Java 集合框架(Java Collections Framework,JCF)提供了一套统一的接口和类,用于处理对象集合。接口:定义了集合类的基本行为和操作。实现类:提供了接口的具体实现,如ArrayListLinkedListHashMap等。算法:提供了一些通用的算法,如排序、搜索等。在 Java 编程中,集合类是处理一组对象的核心工具。Java 提供了丰富的集合类库,包括ListSetQueue和Map等接口及其具体实现类。

xycxycooo的博客 926

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【JAVA】哪些集合类是线程安全的

在多线程编程中,对共享数据的安全访问是一个关键的问题。Java提供了一些线程安全的集合类,以便开发者能够在多线程环境下安全地进行数据操作。深入理解这些线程安全的集合类的特性和适用场景,对于构建高效且稳定的多线程应用至关重要。线程安全的集合类为我们提供了在多线程环境中安全地共享和操作数据的解决方案。从传统的Vector和HashTable到现代的等,这些集合类为不同的并发场景提供了不同的选择。在实际开发中,根据应用程序的需求,选择合适的线程安全集合类是确保多线程程序正确运行的关键。

AliceNo的博客 3235

Java中的集合类

目录 集合类 Collection List Set Map 集合类 我们都知道数组,数组中存放了相同数据类型的数据,数组一旦定义好,数组的长度就不可变化了。但是如果我们需要保存一个可以动态变化的数据(在编译时无法确定具体的数量),java的集合类就是一个很好的设计方案了。 集合类位于 java.util 包下,集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。 Java...

谢公子的博客 1952

java 常用集合类总结

在平常的代码开发中,集合类是经常会使用到的,比如用于列表缓存的ArrayList,用于做映射关系的Map等等 最近重点看了下java集合类的层次继承关系和内部存储结构,做个总结以便后面可以随时翻翻。        java中的集合,不管是List,Set,还是Map,都是继承自collection接口,这个接口主要定义了集合类的一些公关方法,比如isEmpty(), remove(),

peterzhihua的博客 4442

java集合类运用实例_Java集合类实例解析

《Java集合类实例解析》由会员分享,可在线阅读,更多相关《Java集合类实例解析(11页珍藏版)》请在人人文库网上搜索。1、Java集合类实例解析我们看一个简单的例子,来了解一下集合类的基本方法的使用:import java.util.*; public class CollectionToArray public static void main(String args) Collection...

weixin_36444911的博客 363

Java集合中List,Set以及Map等集合体系详解(史上最全)

概述: List Set Map都是接口,前两个继承至Collection接口,Map为独立接口 Set下有HashSet,LinkedHashSet,TreeSet List下有ArrayList,Vector,LinkedList Map下有Hashtable,LinkedHashMap,HashMap,TreeMap 还有Collection接口下还有个Queue接口,有Priority...

君羊 34万+
上一篇: Java线程详解
下一篇: Android Studio 配置NDK环境
HHcoco
博客等级 码龄13年 46粉丝 26原创
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值