首页
学习
活动
专区
工具
TVP
发布

Java中非常重要的概念:Java集合

Java集合是Java中非常重要的概念,用于存储和操作数据。在Java中,集合框架(Collection Framework)是一组接口和类,用于表示和操作集合。这些集合可以存储不同类型的对象,例如整数,字符串,对象等。在这篇文章中,我们将讨论Java集合的主要类型和其用途。

List接口与接口实现类:有序、不唯一

List是Java集合中最常用的接口之一,它允许我们按特定顺序存储元素。List允许重复元素,并且可以根据元素的索引进行访问。在Java中,常见的List实现包括ArrayList和LinkedList。

ArrayList是基于数组实现的,是一个动态数组,可以动态增加和缩减数组的大小。它的查询效率很高,但是插入和删除操作的效率较低。LinkedList是基于链表实现的,可以快速插入和删除元素,但是查询效率相对较低。

ArrayList

内部是通过数组实现的,允许对元素进行快速随机访问。

当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。

适合随机查找和遍历,不适合插入和删除。当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。

LinkedList

LinkedList 是用链表结构存储数据的。

很适合数据的动态插入和删除,随机访问和遍历速度比较慢。

有List 接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。

Vector(线程安全)

通过数组实现的。

默认情况下 Vector 每次扩容时容量都会翻倍。

支持线程的同步,即某一时刻只有一个线程能够写 Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问 ArrayList 慢 。

CopyOnWriteArrayList

写操作在一个复制的数组上进行,读操作还是在原始数组中进行,读写分离,互不影响。

写操作需要加锁,防止并发写入时导致写入数据丢失。

写操作结束之后需要把原始数组指向新的复制数组。

在写操作的同时允许读操作,大大提高了读操作的性能,因此很适合读多写少的应用场景。

内存占用:在写操作时需要复制一个新的数组,使得内存占用为原来的两倍左右。

数据不一致:读操作不能读取实时性的数据,因为部分写操作的数据还未同步到读数组中。

Set接口与接口实现类:无序、不可重复

Set是Java集合中另一个常见的接口,它允许我们存储无序的元素,但不允许重复元素。在Java中,常见的Set实现包括HashSet和TreeSet。

HashSet是基于哈希表实现的,可以快速地添加、删除和查询元素。由于HashSet是无序的,因此不能保证元素的顺序。TreeSet是基于红黑树实现的,可以对元素进行排序,因此可以保证元素的顺序。

HashSet

哈希表边存放的是哈希值。

HashSet这个类实现了Set集合,实际为一个HashMap的实例。

HashSet 存储元素的顺序并不是按照存入时的顺序。而是按照哈希值来存的所以取数据也是按照哈希值取得。元素的哈希值是通过元素的hashcode 方法来获取的, HashSet 首先判断两个元素的哈希值,如果哈希值一样(哈希冲突,也叫哈希碰撞),接着会比较equals 方法 如果 equls 结果为 true,HashSet 就视为同一个元素。如果 equals 为 false 就不是同一个元素。HashSet 通过 hashCode 值来确定元素在内存中的位置。一个 hashCode 位置上可以存放多个元素。

LinkedHashSet

能保证怎么存就怎么取的set集合对象。

LinkedHashSet是一个哈希表和链表的结合,且是一个双向链表。

LinkedHashSet 底层使用 LinkedHashMap 来保存所有元素。

继承与 HashSet,其所有的方法操作上又与 HashSet 相同。

TreeSet

TreeSet是使用二叉树的原理对新添加的对象按照指定的顺序排序(升序、降序),每增加一个对象都会进行排序,将对象插入的二叉树指定的位置。

Integer 和 String 对象都可以进行默认的 TreeSet 排序,而自定义类的对象是不可以的, 自己定义的类必须实现 Comparable 接口,并且覆写相应的 compareTo()函数,才可以正常使用。

在覆写 compare()函数时,要返回相应的值才能使 TreeSet 按照一定的规则来排序。

比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

Map接口与接口实现类

不能包含重复的键、每个键最多只能映射到一个值

Map是Java集合中一种键值对的集合,它允许我们使用键来访问值。Map中的键是唯一的,但值可以重复。在Java中,常见的Map实现包括HashMap和TreeMap。

HashMap是基于哈希表实现的,可以快速地添加、删除和查询键值对。由于HashMap是无序的,因此不能保证键值对的顺序。TreeMap是基于红黑树实现的,可以对键进行排序,因此可以保证键值对的顺序。

LinkedHashMap

迭代顺序可以是插入顺序。

Key和Value都允许空,Key重复会覆盖、Value允许重复。

LinkedHashMap 是 HashMap 的一个子类,保存了记录的插入顺序,在用 Iterator 遍历。

LinkedHashMap 时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。

HashMap

HashMap 根据键的 hashCode 值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。

HashMap 最多只允许一条记录的键为 null,允许多条记录的值为 null。

HashMap 非线程安全,即任一时刻可以有多个线程同时写 HashMap,可能会导致数据的不一致。

如果需要满足线程安全,可以用 Collections 的 synchronizedMap 方法使

HashMap 具有线程安全的能力,或者使用 ConcurrentHashMap。

TreeMap

TreeMap 实现 SortedMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。如果使用排序的映射,建议使用 TreeMap。

key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的Comparator,否则会在运行时抛出 java.lang.ClassCastException 类型的异常。

Hashtable(线程安全)

Hashtable 是遗留类,很多映射的常用功能与 HashMap 类似。

承自 Dictionary 类。

是线程安全的,任一时间只有一个线程能写 Hashtable。

并发性不如 ConcurrentHashMap,因为 ConcurrentHashMap 引入了分段锁。Hashtable 不建议在新代码中使用,不需要线程安全的场合可以用 HashMap 替换,需要线程安全的场合可以用 ConcurrentHashMap 替换。

ConcurrentHashMap线程安全

ConcurrentHashMap 和 HashMap 思路是差不多的。

支持并发操作。

整个 ConcurrentHashMap 由一个个 Segment 组成, Segment 代表”部分“或”一段“的意思,所以很多地方都会将其描述为分段锁。注意,行文中,我很多地方用了“槽”来代表一个segment。

线程安全处理方法

ArrayList、LinkedList和Vector的区别

ArrayList: 可以看作是能够自动增长容量的数组。

ArrayList底层的实现是Array, 数组扩容实现。

ArrayList根据下标查询快,但是根据值查数据速度和LinkList一样。

ArrayList线程不安全,效率高。

LinkList是一个双链表,在添加和删除元素时具有比ArrayList更好的性能。

LinkList线程不安全,效率高。

Vector底层数据结构是数组,查询快,增删慢。

Vector线程安全,效率低。

HashMap和HashTable的区别

HashMap是线程不安全的,所以效率远远高于Hashtable,当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap,ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。

HashMap:key可以为null,但是这样的key只能有一个,因为必须保证key的唯一性可以有多个key值对应的value为null。

Hashtable是线程安全的,它的每个方法上都有synchronized 关键字。

Hashtable:key和value都不能为null。

List、Set、Map三者的区别

List:有序、不唯一。

Set :无序、唯一。

Map:不能包含重复的键、每个键最多只能映射到一个值、元素存储循序是无序的、以键值对存储数据。

Queue

Queue是Java集合中一种特殊的集合,它允许我们按照特定顺序添加和删除元素。队列通常使用FIFO(先进先出)的方式来管理元素。在Java中,常见的Queue实现包括LinkedList和PriorityQueue。

LinkedList是基于链表实现的,可以快速地添加和删除元素。PriorityQueue是基于堆实现的,可以对元素进行排序,因此可以保证元素的顺序。

Java集合框架提供了多种数据结构来存储和操作数据。在选择哪种集合类型时,需要考虑要存储的数据类型以及所需的操作类型。对于需要按照特定顺序存储元素的情况,可以使用List。对于需要存储无序元素且不允许重复的情况,可以使用Set。对于需要使用键值对的情况,可以使用Map。对于需要特定顺序添加和删除元素的情况,可以使用Queue。

希望这篇文章可以帮助您更好地了解Java集合,并在实际开发中正确地选择和使用Java集合。

Java如何入门

Java300集的学习路线图完整版

根据学习线路学习,这套教程是专门为零基础的学生制作的。它适合于零基础的准备开始Java开发的学生。视频中穿插了许多实用的项目。每一个知识点都以浅显易懂的方式讲解,由浅入深。

不仅适合零基础初学者,有经验的程序员也可以做巩固学习。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230313A02VO200?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券