List、Map、Set 三个接口存取元素时,各有什么特点

news/2024/10/18 14:32:17/

List、Map、Set是Java集合框架中的三个核心接口,它们在存取元素时各自具有独特的特点。以下是对这三个接口存取元素特点的详细分析:

List接口

  • 有序性

List中的元素是有序的,它们按照插入的顺序进行排列。

  • 可重复性

List允许存储重复的元素,即List中可以有多个相同的元素。

  • 索引访问

List提供了基于索引的访问方式,可以通过索引(位置)来访问和修改List中的元素。这类似于数组的访问方式。

  • 实现类

List接口的主要实现类包括ArrayList和LinkedList。ArrayList基于动态数组实现,适合随机访问,但插入和删除效率较低;LinkedList基于双向链表实现,插入和删除操作效率高,但查询效率较低。

Set接口

  • 元素唯一性

Set中的元素是唯一的,不允许重复。如果尝试向Set中添加一个已经存在的元素,则添加操作会失败。其实通过查看源码就知道其实是Set的add方法中通过map不能存储重复的key来保证唯一的,Set 集合的 add 方法有一个 boolean 的返回值,当集合中没有某个元素,此时 add 方法可成功加入该元素时, 则返回 true,当集合含有与某个元素 equals 相等的元素时,此时 add 方法无法加入该元素, 返回结果为 false

public boolean add(E e) {return map.put(e, PRESENT)==null;
}
  • 无序性

Set中的元素没有特定的顺序,即不保证元素存储的顺序与插入顺序一致。但是,某些Set的实现类(如LinkedHashSet)可以维护元素的插入顺序。

  • 无索引访问

Set不支持通过索引来访问和修改元素。它主要通过迭代器(Iterator)或增强型for循环来遍历元素。

  • 实现类

Set接口的主要实现类包括HashSet、LinkedHashSet和TreeSet。HashSet基于哈希表实现,查找效率高,但不保证顺序;LinkedHashSet继承自HashSet,使用双向链表维护插入顺序;TreeSet基于红黑树实现,可以按元素的自然顺序或自定义顺序进行排序。

HashSet延伸:
HashSet的存储方式

注意HashSet的存储方式是按照 hashcode 值的某种运算方式进行存储,而不是直接按 hashCode 值的大小进行存储。通过查看源码可以看到运算方式如下:

static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
HashSet如何比较相等

在 Java 中,HashSet 是一个基于哈希表的数据结构,用于存储不重复的元素。当你将一个对象添加到 HashSet 中时,它会根据对象的哈希码(通过调用对象的 hashCode() 方法)来确定该对象应该存放在哪个桶(bucket)中。为了确定两个对象是否相等,HashSet 依赖两个条件:

  1. 哈希码相等:两个对象的哈希码必须相等。这是通过调用对象的 hashCode() 方法来确定的。
  2. equals 方法:如果两个对象的哈希码相等,那么 HashSet 会进一步调用对象的 equals() 方法来确认它们是否确实相等。

因此,要使 HashSet 正确比较两个对象是否相等,必须满足以下要求:

  • 覆盖 hashCode() 方法:确保两个相等的对象具有相同的哈希码。
  • 覆盖 equals() 方法:确保 equals() 方法定义了两个对象相等的逻辑。

 代码实例:

class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}public class HashSetEqualsTest {public static void main(String[] args) {HashSet<Student> set = new HashSet<>();Student p1 = new Student("Alice", 30);Student p2 = new Student("Alice", 30);set.add(p1);set.add(p2);System.out.println("Set size: " + set.size()); // 输出应为 1,因为 p1 和 p2 相等System.out.println(set); // 输出 Student{name='Alice', age=30}}
}

输出结果:

Set size: 1
[Student{name='Alice', age=30}]

 如果Student不实现hashcodeequals方法,则输入结果如下:

Set size: 2
[Student{name='Alice', age=30}, Student{name='Alice', age=30}]

Map接口

  • 键值对存储

Map以键值对(key-value)的形式存储数据。每个键都是唯一的,但值可以重复。

  • 无序性

Map中的键值对没有特定的顺序,即不保证键值对的存储顺序与插入顺序一致。但是,某些Map的实现类(如LinkedHashMap和TreeMap)可以维护键值对的顺序。

  • 键的唯一性

Map中的键是唯一的,每个键最多映射到一个值。Map使用键的equals()和hashCode()方法来比较键是否相等。

  • 值的多重性

Map中的值可以重复,即多个键可以映射到相同的值。

  1. 实现类

Map接口的主要实现类包括HashMap、TreeMap、Hashtable、LinkedHashMap和ConcurrentHashMap。HashMap基于哈希表实现,查找效率高,但不保证顺序;TreeMap基于红黑树实现,按键的自然顺序或自定义顺序进行排序;LinkedHashMap继承自HashMap,使用双向链表维护插入顺序或访问顺序;Hashtable是线程安全的HashMap,但性能较低;ConcurrentHashMap是线程安全的HashMap,适用于高并发场景。

总结

综上所述,List、Map、Set三个接口在存取元素时各有其独特的特点。List适合存储有序的元素列表,并允许重复元素;Set适合存储不重复的元素集合,并提供了高效的查找性能;Map则适合存储键值对映射,其中键是唯一的,而值可以重复。在选择使用哪个接口时,应根据具体的应用场景和需求来决定。


http://www.ppmy.cn/news/1538819.html

相关文章

Mac上功能全面,免费好用的解压缩工具

在日常使用Mac的过程中&#xff0c;相信不少朋友都有解压缩需求&#xff0c;目前存在的解压缩软件可以说各种各样&#xff0c;但是有的收费&#xff0c;有的解压速度慢&#xff0c;有的解压类型不全&#xff0c;各有优缺点&#xff0c;挑选起来眼花缭乱&#xff0c;挑来挑去也没…

taozige/Java语言的Netty框架+云快充协议1.5+充电桩系统+新能源汽车充电桩系统源码

云快充协议云快充1.5协议云快充1.6云快充协议开源代码云快充底层协议云快充桩直连桩直连协议充电桩协议云快充源码 介绍 云快充协议云快充1.5协议云快充1.6云快充协议开源代码云快充底层协议云快充桩直连桩直连协议充电桩协议云快充源码 软件架构 1、提供云快充底层桩直连协…

电脑无线网wifi和有线网同时使用(内网+外网同时使用)

一、要求 我这里以无线网wifi为外网&#xff0c;有线网卡为内网为例&#xff1a; 一、基本信息 无线wifi&#xff08;外网&#xff09;&#xff1a;ip是192.168.179.235&#xff0c;网关是192.168.179.95有线网&#xff08;内网&#xff09;&#xff1a;ip是192.168.10.25&…

前端 + Nginx + 后端架构的无感升级方案

一、前端无感升级 构建新的前端包 使用 Webpack、Vite 等工具进行打包&#xff0c;生成带有版本号或哈希值的静态文件名。确保 index.html 引用最新的静态资源文件&#xff08;例如 app.js?versionabc123&#xff09;。 上传静态资源到服务器 将打包后的前端静态资源上传到 Ng…

并查集的实现(朴素版)

这是C算法基础-数据结构专栏的第二十九篇文章&#xff0c;专栏详情请见此处。 由于作者即将参加CSP&#xff0c;所以到比赛结束前将不再发表文章&#xff01; 引入 并查集是一种可以快速合并查找集合的一种数据结构&#xff0c;这次我们将通过三道题来详细讲解并查集&#xff…

一文了解 Linux 系统的文件权限管理

文章目录 引入Linux文件权限模型查看文件权限权限信息解析修改文件权限符号模式八进制数字模式 引入 在Linux操作系统中&#xff0c;我们想查看我们对文件拥有哪些权限时&#xff0c;可以在终端键入ls -l或ll命令&#xff0c;终端会输出当前路径下的文件信息&#xff0c;如文件…

力扣10.10

329. 矩阵中的最长递增路径 给定一个 m x n 整数矩阵 matrix &#xff0c;找出其中 最长递增路径 的长度。 对于每个单元格&#xff0c;你可以往上&#xff0c;下&#xff0c;左&#xff0c;右四个方向移动。 你 不能 在 对角线 方向上移动或移动到 边界外&#xff08;即不允…

【Coroutines】Implement Lua Coroutine by Kotlin - 2

Last Chapter Link 文章目录 Symmetric CoroutinesNon-Symmetric Coroutine SampleSymmetric Coroutine SampleHow to Implement Symmetric CoroutinesWonderful TricksCode DesignTail Recursion OptimizationFull Sources Symmetric Coroutines in last blog, we have talk…