news 2026/4/3 4:25:01

java学习日志--集合(Collection篇)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java学习日志--集合(Collection篇)

一、集合框架

1.1 集合概述

集合:广义上的集合简单理解就是容器。需要注意的是,集合只能存放对象类型的数据。

所以如果你要存放基本数据类型的数据是不能直接存储的,需要转化成包装类,包装类详见常见类库(下)。

1.2 集合框架

集合框架是Java中非常重要的技术体系,在日常开发中无处不在。

集合框架指的是java.util包中定义的各种容器类、相关的工具类、接口的统称。不同的容器存储不同结构的数据。使用时要进行导包操作。

具体集合的框架的体系图如下:

其中,Iterator是根部的父接口,总结来说,接口一共分为两大类(三小类),分别是Collection和Map(List,Set和Map)。

具体特性如上图所示(以下无序是指在逻辑上的有无序),

List是有序可重复的集合,实现类有ArrayList,LinkedList;

Set是无序不可重复的集合,实现类有HashSet,TreeSet,LinkedHashSet;

Map里面存放的是无序的具有映射关系的键值对,实现类有HashMap,LinkedHashMap,TreeMap。

二、Collection接口

2.1 Collection接口概述

具体Collection接口的类结构见1.2中的图所示,实际上,其中TreeSet上面是有一个父类SortedSet的,后面的某一个点会有要提到的地方。

在常见类库(上)中我们我们有提到,了解一个类可以从它的定位,也就是作用,和它的构造器,以及它的成员来学习,同样,接触到了一个新的接口,我们先看一下它的结构。

Collection接口继承了Iterator,在Iterator接口中,规定了实现类必须要提供迭代器对象,在Java中使用迭代器去遍历集合中的元素,这是一种新的遍历方法,在学习此之前都是循环遍历。

Collection作为Iterable接口的子接口,意味着Collection接口的实现类一定会实现Iterable接口中规定的方法;List、Set接口的实现类也一定会实现Iterable接口中规定的方法。

2.2 Collection接口的方法

因为它是一个接口,所以其中定义的大多都是抽象方法,是没有方法体的。

详细的方法如下:

//获取集合中元素的个数。 int size() //向集合中添加元素,添加后如果容器内容发生了变化,返回true,否则返回false。 //有些容器不允许重复元素。 boolean add(E e) //将指定集合中的元素添加到当前集合中,添加后如果容器内容发生了变化,返回true,否则返回false。 booleanaddAll(Collection <? extends E > c) //从集合中删除指定的元素,删除后如果容器内容发生了变化,返回true,否则返回false。 boolean remove(Obiect 0) //删除指定集合中包含的全部元素,删除后如果容器内容发生了变化,返回true,否则返回false。 boolean removeAl(Collection<?>c) //删除集合中全部元素。 void clear() //判断集合中是否包含指定的元素。 boolean contains(Object0) //判断集合中是否包含指定集合中全部元素。 boolean containsAll(Collection<?> c) //获取集合对应的迭代器。(迭代器可以遍历集合) Iterator<E>iterator() //判断是不是空集合 boolean isEmpty() //将集合转换成对象数组。 Object[] toArray()

因为List接口和Set接口继承了该接口,所以这些方法在这些接口及其实现类中也是可以调用的,如果没有涉及到改动,在下面的讲述中就只总结新遇到的方法。

三、List接口

3.1 List接口概述

List 是一个“有顺序、可重复”的集合,像排队一样,每个元素都有固定位置(索引),所以这个有序指的是逻辑是否有序。

因为存在下标,所以List可以利用下表去做一些不同的事,也就是它定义了自己的一些关于下标的方法。

3.2 List接口的方法

//在集合指定的位置添加元素。 void add(int index,E e) //在集合中指定的位置添加一组元素 void addAll(int index, Collection<?extends E> c) //获取集合中指定位置的元素。 E get(int index) //获取对象第一次出现在集合中的下标。如果没有这个对象返回-1。 int indexOf(Object o) //获取对象最后一次出现在集合中的下标。如果没有返回-1。 int lastindexOf(Object o) //删除指定下标的元素,返回值是被删除的元素。 E remove(int index) //将指定位置的元素修改成e,返回值是此位置原来的元素。 E set(int index, E e) //获取子列表。不含toIndex对应的元素 List< E> subList(int fromIndex, int tolndex)

3.3 List接口的实现类

因为讲的是集合,集合是要存放数据的,关于数据就要涉及到增删改查,这方面是重点,所以下面我们重点介绍一下相关的增删改查的一些方法。

3.3.1 ArraysList实现类

ArraysList实现类的底层逻辑是数组,有关数组的逻辑在这里就不再多讲了吧,如果对数组的内存有疑问也可以去查看我之前的文章。

同时,这个数组存放又和我们之前的数组有些不同,ArrayList是长度可变的数组,长度不足时会自动扩充容量。

由于底层是靠数组完成的数据存取,所以查询效率高(根据index查询),增删效率低。

具体逻辑:因为数组有下标,根据索引可以很快地找到对应的数据,但是又因为数组结构在存放上是物理有序的,所以当我们需要增删时,我们需要随之对后续的数据都要进行前移或后挪,所以查询效率高(根据index查询),增删效率低。

3.3.1.1 构造器
//创建一个初始容量为10的空列表。 ArrayList() //创建一个列表,包含参数中全部的元素,顺序与参数中元素的顺序一致。 ArrayList(Collection<? extends E> c) //创建一个指定容量的空列表。 ArrayList(int capacity)
3.3.1.2 增删改查

1)增

//向ArrayList中添加一个元素,元素会添加到ArrayList的末尾。如果添加成功,返回true boolean add(E e) //在指定位置插入元素。 void add(int index, E e) //将指定集合中的数据按顺序添加到ArrayList的末尾。 boolean addAll(Collection<? extends E> c) //将指定集合中的数据插入到ArrayList的指定的位置。 boolean addAll(int index, Collection<? extends E> c)

2)删

//从列表中删除指定的元素,如果有多个,只会删除第一个。如果成功删除返回true,如果没有删除返回false。 boolean remove(Object o) //删除指定位置的元素。返回值是被删除的元素。 E remove(int index) //从列表中删除指定集合中包含的元素。如果列表删除了数据返回true,否则返回false。 boolean removeAll(Collection<? extends E> c) //清空列表中的元素 void clear()

3)改

E set(int index, E e) //将指定下标的元素修改为e

4)查

  • 是否包含此元素
//判断列表中是否包含指定的元素,如果包含返回true,否则返回false。 boolean contains(Object o)
  • 获取指定下标的元素
E get(int index) //获取指定下标处的元素。
  • 根据元素获取下表
//返回列表中指定元素第一次出现的下标。如果没有指定元素返回-1 int indexOf(Object o) //返回列表中指定元素最后一次出现的下标。如果没有指定元素返回-1 int lastIndexOf(Object o)
  • 获取列表中元素的个数
int size() //获取列表中元素的个数
3.3.1.3 ArraysList的遍历

作为数组的存储方式,ArraysListu也可以使用普通for循环进行遍历。

  • 通过普通for循环遍历
for(int i = 0; i < arrayList.size(); i++){ arrayList.get(i); }
  • 加强for循环
for(数据类型 对象 : arrayList){ 对象;//对象就是遍历出来的数据 }
  • 迭代器循环
//调用iterator方法返回的值赋给新建的Iterator对象,使用该对象调用对应的方法进行迭代器循环 Iterator<数据类型> it = arrayList.iterator(); while(it.hasNext()){ 数据类型 对象 = it.next(); }

3.3.2 LinkedList实现类

LinkedList底层是靠双向链表来存放元素的。链表中的元素在逻辑上连续,但物理上不连续。因此,LinkedList增、删效率高,增删元素无需做任何移动,直接改变链表的指向即可。但根据下标查找元素效率低。

3.3.2.1 构造器
//创建一个空列表。 LinkedList() //创建一个列表,包含参数中全部的元素,顺序与参数中元素的顺序一致。 LinkedList(Collection<? extends E> c)
3.3.2.2 增删改查

因为都是有下标的集合,所以在增删改查方面和ArraysList基本相同,由于内容较多,在此就不再多赘述,详细查看3.3.1.2 。

3.3.2.3 LinkedList的遍历

  • 通过普通for循环遍历
for(int i = 0; i < LinkedList.size(); i++){ LinkedList.get(i); }
  • 加强for循环
for(数据类型 对象 : LinkedList){ 对象;//对象就是遍历出来的数据 }
  • 迭代器循环
//调用iterator方法返回的值赋给新建的Iterator对象,使用该对象调用对应的方法进行迭代器循环 Iterator<数据类型> it = LinkedList.iterator(); while(it.hasNext()){ 数据类型 对象 = it.next(); }

四、Set接口

4.1 Set接口概述

Set接口规定了无序(无下标),元素不可重复的容器应该具有什么功能。既然是不含重复元素的集合,那它就具有排除重复元素的能力。

所以我们在进行Set接口的总结时也要加上它相关的去重原理。

4.2 Set接口的方法

Set接口中并没有声明多少独特的方法,而是声明了和父接口相同的方法。

所以具体的方法和Collection接口,也就是父接口中的相同,再次也不过多赘述,详情请见2.2内容

4.3 Set接口的实现类

4.3.1 HashSet实现类

HashSet实现类中存储的数据是不重复的,元素的顺序也是无序的。底层数据结构是哈希表。

在学习这一块时我问过AI,它给了我一个比较形象的例子,说它就像是你要往一面墙上贴照片,墙上的每个位置都有一个自己的编码(哈希码),当来了一个照片(数据),就会根据它的内容找到(生成)一个位置(哈希码),然后贴上去。如果墙上的那个位置已经存在照片,就说明已经贴过了,这就是一种查重。

4.3.1.1 HashSet的构造器
//创建一个空集合,集合的初始容量是16,加载因子是0.75 HashSet() //创建一个包含指定元素的集合,会去除重。加载因子是0.75 HashSet(Collection<? extends E> c) //创建一个指定初始容量的空集合。加载因子是0.75 HashSet(int capacity) //创建一个空集合,指定初始容量和加载因子。 HashSet(int capacity, float loadFactor)
4.3.1.2 HashSet的方法

1)增

//向集合中添加一个元素,如果添加成功,返回true boolean add(E e) //将指定集合中的数据添加到HashSet中,会去重。 boolean addAll(Collection<? extends E> c)

2)删

//从集合中删除指定的元素,如果成功删除返回true,如果没有删除返回false(例如:没有指定的元素)。 boolean remove(Object o) //从HashSet中删除指定集合中包含的元素。如果删除了数据返回true,否则返回false。 boolean removeAll(Collection<? extends E> c) //清空集合中的元素 void clear()

3)改

因为HashSet没有下标,且是无序的,所以无法进行修改数据,所谓的修改,是通过for循环或者迭代器进行的一种删除数据再添加的操作。

4)查

//判断集合中是否包含某元素 boolean contains(Object o) //获取集合中元素的个数。 int size()
4.3.1.3 HashSet的去重机制

我们可以先将List集合转化成Set集合,再转换回来,就可以达到去重的目的。

1)先判断对象的hashCode是否一样,如果hashCode不同,认为是不同的元素。如果hashCode相同,进入下面的判断。

2.)判断equals方法返回值是true还是false,如果是false认为是不同的元素,如果是true认为是元素重复。不再添加进集合。

3)hashCode可以通过重写根类Object的hashCode()方法来返回一个hashCode值。

但是当我们new两个对象,但是他们的内容完全相同,对于代码而言,他们就是不同的,因为内存地址不同,但是从逻辑上来看,他们就是完全重复的内容。这时候,我们可以通过重写对应类里的hashCode和equals方法,来达到根据我们的条件去重的目的。

4.3.1.4 HashSet的遍历

因为没有下表,所以无法使用普通for循环来进行遍历

  • 加强for循环
for(数据类型 对象 : HashSet){ 对象;//对象就是遍历出来的数据 }
  • 迭代器循环
//调用iterator方法返回的值赋给新建的Iterator对象,使用该对象调用对应的方法进行迭代器循环 Iterator<数据类型> it = HashSet.iterator(); while(it.hasNext()){ 数据类型 对象 = it.next(); }

4.3.2 LinkedHashSet实现类

LinkedHashSet是HashSet的子类,它具有和HashSet同样的功能,元素也是不能重复,唯一不同的是,LinkedHashSet会维持元素加入的顺序。LinkedHashSet和LinkedList一样,底层数据结构是双向链表+哈希表。

4.3.2.1 LinkedHashSet的构造器
//创建一个空集合,集合的初始容量是16,加载因子是0.75 LinkedHashSet() //创建一个包含指定元素的集合,会去除重。加载因子是0.75 LinkedHashSet(Collection<? extends E> c) //创建一个指定初始容量的空集合。加载因子是0.75 LinkedHashSet(int capacity) //创建一个空集合,指定初始容量和加载因子。 LinkedHashSet(int capacity, int loadFactor)
4.3.2.2 LinkedHashSet的方法

因为LinkedHashSet是HashSet的子类,所以详情见4.3.1.2,

4.3.2.3 LinkedHashSet的遍历

见HashSet的遍历4.3.1.4

4.3.3 TreeSet实现类

TreeSet使用的是二叉树存储元素, 通过中序遍历的方式来遍历(检索)元素

二叉树的遍历有3种方式,先序遍历,中序遍历和后序遍历。无论是否哪种遍历方式.都是从树根开始查看的 。

先序:先父节点,再左,最后右ABDECFG

中序:先左,再父,最后右DBEAFCG

后序:先左,再右,最后父DEBFGCA

TreeSet实现类会有一个默认的排序,第一个进入的值在根位置,之后进来的元素都会和第一个元素进行比较,比根小就在左边,比根大就在右边。

4.3.3.1 TreeSet的构造器
//创建一个空集合,根据内部元素的自然顺序排序。 TreeSet() //创建一个包含指定元素的集合,根据内部元素的自然顺序排序。 TreeSet(Collection<? extends E> c) //创建一个空集合。根据指定的比较器进行排序。 TreeSet(Comparator<? super E> comparator) //创建一个与参数一样的集合,按参数的顺序组织元素顺序。 TreeSet(SortedSet<E> s)
4.3.3.2 TreeSet的方法

基本和HashSet的方法相同,在这里我举几个独有的方法吧

//获取集合倒序的迭代器对象 Iterator< E > descendingIterator() //获取集合第一个元素 E first() //获取结合最后一个元素 E last() //获取从from到to的元素。 SortedSet< E > subSet(E from, E to)
4.3.3.3 TreeSet的去重方法

去重和内容有序的原理: 第一个加入set的元素, 会成为树的根, 从第二个元素开始, 要和set中已有的元素比较大小, 如果要添加的元素 大于了已有元素,放在元素右侧, 如果小于了已有元素, 放左侧, 如果要添加的元素和已有元素相等, 会认为重复, 不进行添加 。

4.3.3.4 TreeSet的遍历

因为也是没有下标,所以在遍历方面也基本和HashSet相同,唯独多了一个倒序迭代器,如下。

Iterator<String> it = set.descendingIterator(); while(it.hasNext()) { String str = it.next(); System.out.println(str); }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/25 8:57:00

ZonyLrcToolsX:跨平台歌词下载的终极解决方案

ZonyLrcToolsX&#xff1a;跨平台歌词下载的终极解决方案 【免费下载链接】ZonyLrcToolsX ZonyLrcToolsX 是一个能够方便地下载歌词的小软件。 项目地址: https://gitcode.com/gh_mirrors/zo/ZonyLrcToolsX 还在为音乐收藏中缺少歌词而困扰吗&#xff1f;作为一名音乐爱…

作者头像 李华
网站建设 2026/3/26 15:16:32

告别语言障碍!Screen Translator让你秒变翻译达人

还在为看不懂外文资料而烦恼吗&#xff1f;还在为语言不通而错失重要信息吗&#xff1f;今天我要为你推荐一款神器——Screen Translator&#xff0c;这款屏幕翻译工具将彻底改变你的跨语言工作方式&#xff01;✨ 【免费下载链接】ScreenTranslator Screen capture, OCR and t…

作者头像 李华
网站建设 2026/3/31 21:20:19

LibreVNA开源矢量网络分析仪:从入门到精通的完整指南

LibreVNA开源矢量网络分析仪&#xff1a;从入门到精通的完整指南 【免费下载链接】LibreVNA 100kHz to 6GHz 2 port USB based VNA 项目地址: https://gitcode.com/gh_mirrors/li/LibreVNA LibreVNA作为一款开源的100kHz到6GHz双端口USB矢量网络分析仪&#xff0c;为射频…

作者头像 李华
网站建设 2026/4/1 19:48:39

10分钟掌握弹窗动态数据更新:lay/layer实时渲染完全指南

10分钟掌握弹窗动态数据更新&#xff1a;lay/layer实时渲染完全指南 【免费下载链接】layer 项目地址: https://gitcode.com/gh_mirrors/lay/layer 你是否正在寻找弹窗内容实时更新的终极解决方案&#xff1f;面对静态弹窗无法及时反映数据变化的困境&#xff0c;本文为…

作者头像 李华
网站建设 2026/4/2 12:26:31

香港科技大学新方案:让AI学会炒股的“超级大脑“

由香港科技大学邓哲晔和王嘉舒两位研究者开发的AlphaQuanter系统&#xff0c;就像给人工智能装上了一个专业交易员的大脑。这项发表于2025年1月的研究成果&#xff0c;首次让AI能够像人类交易员一样&#xff0c;主动收集信息、深度分析&#xff0c;并做出交易决策。有兴趣深入了…

作者头像 李华
网站建设 2026/3/26 23:48:29

自适应令牌交叉注意力机制图像超分辨率重建算法复现教程

自适应令牌交叉注意力机制图像超分辨率重建算法复现教程 ATDSR(Adaptive Token Dictionary Super Resolution)自适应令牌字典图像超分辨率重建算法,2024CVPR论文,在Pytorch下搭建,基于Transformer 和 Basicsr,重建结果优于 HAT。这篇文章中含有训练及测试教程,提供可以直…

作者头像 李华