JavaSE学习进阶day05_01 Collection集合

news2024/11/13 15:19:46

第九章 Collection集合

9.1 集合概述

在前面基础班我们已经学习过并使用过集合ArrayList<E> ,那么集合到底是什么呢?

  • 集合:集合是java中提供的一种容器,可以用来存储多个数据。

集合和数组既然都是容器,它们有什么区别呢?

  • 数组的长度是固定的。集合的长度是可变的

  • 数组中存储的是同一类型的元素,可以存储任意类型数据。集合存储的都是引用数据类型。如果想存储基本类型数据需要存储对应的包装类型。(注意回顾包装类型哦)

小结:

9.2 集合常用类的继承体系

Collection特点:

Collection集合体系:

Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.Listjava.util.Set。其中,List的特点是元素有序、有索引、元素可重复Set的特点是无序、无索引、元素不可重复List接口的主要实现类有java.util.ArrayListjava.util.LinkedListSet接口的主要实现类有java.util.HashSetjava.util.LinkedHashSet

从上面的描述可以看出JDK中提供了丰富的集合类库,为了便于初学者进行系统地学习,接下来通过一张图来描述集合常用类的继承体系

注意:这张图只是我们常用的集合有这些,不是说就只有这些集合

集合本身是一个工具,它存放在java.util包中。在Collection接口定义着单列集合框架中最最共性的内容。

9.3 Collection 常用API

Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:

  • public boolean add(E e): 把给定的对象添加到当前集合中 。

  • public void clear() :清空集合中所有的元素。

  • public boolean remove(E e): 把给定的对象在当前集合中删除。

  • public boolean contains(Object obj): 判断当前集合中是否包含给定的对象。

  • public boolean isEmpty(): 判断当前集合是否为空。

  • public int size(): 返回集合中元素的个数。

  • public Object[] toArray(): 把集合中的元素,存储到数组中

tips: 有关Collection中的方法可不止上面这些,其他方法可以自行查看API学习。

代码示例:

public class Demo1 {
    public static void main(String[] args) {
        //强调:以后该怎么创建对象,还是怎么创建对象
        //现在我们是为了要学习Collection接口中的方法
        //所以才用多态方式创建对象的。
​
        Collection<String> list = new ArrayList<>();
        //add方法表示默认将元素添加到末位
        //返回值表示当前元素是否添加成功
        //ArrayList一定是添加成功的,所以返回true!这个基础班的时候提到过哦!!
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        System.out.println(list);
        
        
        //清空方法
        //list.clear();
        //System.out.println(list);
        
        
        
        //删除方法 remove(对象)
        //注意:在Collection只有一个删对象的方法,没有通过索引删除的方法
        //因为Collection还有第二个分支:Set。而Set集合是没有索引的。
        //boolean result1 = list.remove("aaa");
        //System.out.println(result1);
        //boolean result2 = list.remove("eee");
        //System.out.println(result2);
        //System.out.println(list);
        
        
        
        //判断是否包含的方法
        //contains 判断是否包含
        boolean result3 = list.contains("aaa");
        System.out.println(result3);
        boolean result4 = list.contains("eee");
        System.out.println(result4);
        
        
        
        //判断集合是否为空
        System.out.println(list.isEmpty());
        
        
        
        
        //获取集合的长度
        System.out.println(list.size());
​
    }
}
​

每一步的运行结果大家自己手动敲运行一下!

第二章 Collection的三种通用遍历方式(掌握)

  • 迭代器遍历

  • 增强for遍历

  • lambda表达式遍历

  • 因为Collection没有索引,所以不能用普通for

注意:

基础班学习的普通for只适用于List集合,而Set没有索引,是不能用普通for遍历的

2.1 Iterator接口

在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.Iterator

想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作,下面介绍一下获取迭代器的方法:

  • public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的。

下面介绍一下迭代的概念:

  • 迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

Iterator接口的常用方法如下:

  • public E next():返回迭代的下一个元素。

  • public boolean hasNext():如果仍有元素可以迭代,则返回 true。

  • 这两个方法是结合使用的,在今后的开发中,这俩方法几乎是形影不离。

接下来我们通过案例学习如何使用Iterator迭代集合中元素:

//1.创建集合
Collection<String> list = new ArrayList<>();
//2.添加元素
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
//3.遍历
//3.1获取迭代器对象(箭头,指针),默认指向集合的0索引位置
Iterator<String> it = list.iterator();
//3.2循环判断当前指向的位置是否有元素
while(it.hasNext()){
    //3.3获取元素并移动指针
    String str = it.next();
    System.out.println(str);
}

tips:

  1. 在进行集合元素获取时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会抛出java.util.NoSuchElementException没有集合元素异常。

  2. 在进行集合元素获取时,如果添加或移除集合中的元素 , 将无法继续迭代 , 将会抛出ConcurrentModificationException并发修改异常.

2.2 迭代器的实现原理

我们在之前案例已经完成了Iterator遍历集合的整个过程。当遍历集合时,首先通过调用t集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,为了让初学者能更好地理解迭代器的工作原理,接下来通过一个图例来演示Iterator对象迭代元素的过程:

在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。

3.3增强for

增强for相当于是迭代器的简化写法。它既可以用于集合也可以用于数组

注意点:

只有实现了Iterable接口的类,才能用增强for和迭代器遍历。

核心:

简化迭代器书写,底层其实也是一个迭代器。

作用:

可以用来遍历集合或者数组

格式:

for(数据类型 变量名: 集合/数组){
    //遍历操作    
}

遍历数组:

之前基础班学过的快捷方式 数组名.fori 然后回车。这是之前遍历数组的快捷方式,现在只需要稍稍改动一下即可 数组名.for 然后回车。注意上诉代码那个int i是一个局部变量,它是用来接收数组元素的。改变它的值不改变数组元素的值!!

索引自动加1不是那个i在自动加1,那个i是用来接收数组元素的,而是整个增强for循环在自动加1

遍历集合:

代码示例:

//1.创建集合
ArrayList<String> list = new ArrayList<>();
//2.添加元素
list.add("aaa");
list.add("bbb");
list.add("ccc");
//3.遍历
for(String str : list){
    System.out.println(str);
}

运行结果:

3.4增强for的注意点:

增强for中的变量,仅仅是一个第三方变量而已,我们是遍历集合得到每一个元素,把每一个元素赋值给第三方变量,如果我们在循环的过程中,修改了第三方变量的值,是不会改变集合里面原本的值

代码示例:

//1.创建集合
ArrayList<String> list = new ArrayList<>();
//2.添加元素
list.add("aaa");
list.add("bbb");
list.add("ccc");
//3.遍历
for(String str : list){
    //此时没有索引的概念
    //str依次表示集合里面的每一个元素
    //System.out.println(str);
    //此时的str仅仅是一个第三方变量而已
    //我们是遍历集合得到每一个元素,把每一个元素赋值给第三方变量
    //如果我们在循环的过程中,修改了第三方变量的值,是不会改变集合里面原本的值。
    str = "QQQ";
}
​
for (int i = 0; i < list.size(); i++) {
    //利用普通for遍历,也是一样的,获取元素赋值给第三方变量
    String str = list.get(i);
    //修改第三方变量的值,不会影响集合中的元素
    str = "QQQ";
}
​
//4.循环结束之后打印集合
System.out.println(list);

3.5lambda表达式遍历集合

遍历用到的方法:

方法名作用
void forEach(Consumer<? super T> action):结合lambda遍历集合

代码示例:

package com.itheima.a03arraylistdemo;
​
import java.util.ArrayList;
import java.util.function.Consumer;
​
public class Demo4 {
    public static void main(String[] args) {
        //1.创建集合
        ArrayList<String> list = new ArrayList<>();
        //2.添加元素
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
​
        //3.遍历集合
        //forEach方法在底层其实也是进行了循环遍历
        //在遍历的过程中,得到了每一个元素,再调用下面的accept方法
         System.out.println("----------匿名内部类-----------------");
        list.forEach(
            new Consumer<String>() {
                @Override
                public void accept(String s) {
                    //参数s,依次表示集合中的每一个数据
                    System.out.println(s);
                }
            }
        );
​
        System.out.println("----------lambda表达式-----------------");
        list.forEach(
            (String s) -> {
                //参数s,依次表示集合中的每一个数据
                System.out.println(s);
            }
        );
​
        System.out.println("----------lambda表达式简写格式-----------------");
        list.forEach(s -> System.out.println(s));//掌握
    }
}
​

3.6 练习-添加自定义对象并遍历

需求:

某影院系统需要在后台存储上述三部电影,然后依次展示出来。

属性:电影名name 评分score 主演acotr

分析

①:定义一个电影类,定义一个集合存储电影对象。

②:创建3个电影对象,封装相关数据,把3个对象存入到集合中去。

③:遍历集合中的3个对象,输出相关信息。

代码示例:

public class Demo5 {
    public static void main(String[] args) {
        //创建集合对象
        Collection<Moive> list = new ArrayList<>();
        //添加元素
        Moive m1 = new Moive("肖生克的救赎", 9.7, "罗宾斯");
        Moive m2 = new Moive("霸王别姬", 9.6, "张国荣、张丰毅");
        Moive m3 = new Moive("阿甘正传", 9.5, "汤姆.汉克斯");
        list.add(m1);
        list.add(m2);
        list.add(m3);
​
        //遍历
        //迭代器
        System.out.println("----------------迭代器-----------------");
        Iterator<Moive> it = list.iterator();
        while (it.hasNext()) {
            Moive moive = it.next();
            System.out.println(moive);
        }
​
        System.out.println("----------------增强for-----------------");
        for (Moive moive : list) {
            System.out.println(moive);
        }
​
        System.out.println("----------------匿名内部类-----------------");
        list.forEach(new Consumer<Moive>() {
            @Override
            public void accept(Moive moive) {
                System.out.println(moive);
            }
        });
​
        System.out.println("----------------lambda表达式-----------------");
        list.forEach((Moive moive) -> {
            System.out.println(moive);
​
        });
        System.out.println("----------------lambda表达式简写格式-----------------");
        list.forEach(moive -> System.out.println(moive));
    }
}
​

这个代码能自己手动写出来而且要熟练就差不多掌握了。在此强调,Lamada表达式和匿名内部类联席紧密,学不好匿名内部类就理解不了Lambda表达式Lambda表达式和Lambda式的简写是非常重要且容易忘记的内容,大家学习的时候这部分多花一点时间。因此在学习这几节内容时,最好一起学习。一起练习,综合练习才能掌握更牢固。

集合内存分布:

集合存的不是对象本身,而是该对象的地址,通过该地址找到该对象

扩展:如果集合中存储的是自定义对象,那么在利用contains判断元素是否存在和利用remove删除元素时,要重写equals方法。为什么?

首先我们要知道一点的是,当我们判断一个对象属不属于该集合不是看这个对象的地址是不是和该集合的某个元素地址一致,而是看该对象的所有属性和几集合的某个元素的所有属性是否一致。打个比方:就好比入你在某高中高三5班读书,但是现在你在家,我们判断你属不属于5班不是看你现在所在的地址是不是和高三五班这个班级的地址是否一致。而是看你的属性值和当前班级的某个成员是否一致。如果一致那你就属于这个班级

这是结论,下面我来讲解为什么?如下:

学生对象s1和s2是不同的对象,但是他们的属性是一样的,也就是说给我们的感觉是他俩是同一个人,只是所在地址不同。但是学生s2没有添加到集合中,判断这个元素是否在集合中用contains方法。答案是false,说明不再集合中,但是s1的属性和s2的属性一模一样,理应来说应该在集合中才对。那么是怎么判断的呢?可以把当前contains转到定义看一下。

这里的equals是Object类的equals,它是用 ==比较的。比较的是地址值但是我们对一个对象在不在集合中不是用地址进行判断,而是判断这个对象的属性是不是和集合中某个元素的属性相等。因此要在Student类中重写equals方法。

重写后再运行如下,这是重写的,前面学习Object已经学过怎么重写了,快捷键

alt+insert,选择equals即可

重写后再次运行:

同理,remove方法同理。

这是在没有重写equals方法时删除对象的结果,和上面一样,在没有重写的情况下是调用Object类里的equals方法,进行的是地址的比较。我们删除元素肯定是删除指定属性对象的元素。要达到这样的效果,就得重写equals方法。重写它以后,就进行的是属性之间的比较。

重写后再运行:

疑问:为什么重写equals方法就可以呢?我们转到集合类的remove方法的定义看一下:

再点击equals转到定义发现就是跳转到Object类的equals方法即他们比较的是地址值,但是我们判断一个对象属不属于该集合中不是看这个对象的地址,二是看该对象的所有属性值是不是和集合中某个元素的所有属性值一致。因此要重写equals方法

总结:使用集合时一定要重写equals方法!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华特转债上市价格预测

华特转债 基本信息 转债名称&#xff1a;华特转债&#xff0c;评级&#xff1a;AA-&#xff0c;发行规模&#xff1a;6.46亿元。 正股名称&#xff1a;华特气体&#xff0c;今日收盘价&#xff1a;93.75元&#xff0c;转股价格&#xff1a;84.22元。 当前转股价值 转债面值 / …

如何成为一名优秀的自动化测试开发工程师?

目录 前言 精通编程语言 掌握自动化测试框架 熟悉测试方法和流程 熟练使用测试工具 具备团队协作能力 学习新技术和工具 以下是更为具体的建议&#xff1a; 总结 前言 自动化测试作为软件测试领域中发展最快的一个分支&#xff0c;已经成为了许多企业提升软件质量和效…

C语言断言函数的应用

对于断言&#xff0c;相信大家都不陌生&#xff0c;大多数编程语言也都有断言这一特性。简单地讲&#xff0c;断言就是对某种假设条件进行检查。 在 C 语言中&#xff0c;断言被定义为宏的形式&#xff08;assert(expression)&#xff09;&#xff0c;而不是函数&#xff0c;其…

vue element-ui web端 引入高德地图,并获取经纬度

发版前接到一个临时新需求 &#xff0c;需要在web端地址选择时用地图&#xff0c;并获取经纬度。 临阵发版之际加需求&#xff0c;真的是很头疼&#xff0c;于是赶紧找度娘&#xff0c;找api。 我引入的是高德地图&#xff0c;首先要去申请key &#xff0c; 和密钥&#xff0c;…

【Typora-使用手册】Typora使用手册 常用设置 常用快捷键

【Typora-使用手册】Typora使用手册 & 常用设置 & 常用快捷键 1&#xff09;Typora简介1.1.Typora是什么1.2.下载地址1.3.下载注意事项 2&#xff09;Markdown语法总结2.1.标题编写2.1.1.大标题2.1.2.小标题 2.2.单选框2.3.删除线2.4.表情包2.5.字体加粗2.6.斜体2.7.表…

4.HDFS概述

如果说HDFS是存储,则Yarn就是cpu和内存,mapreduce就是程序。 1.HDFS文件块大小 HDFS中的文件在物理.上是分块存储(Block) ,block默认保存3份块的大小可以通过配置参数(dfs blocksize)来规定,默认大小在Hadoop2 .x版本中是128M,老版本中是64M。 解释:块的大小:10ms*100*…

分布式链路追踪—SkyWalking

文章目录 1. 总览2. 为什么要使用分布式链路追踪3. 了解OpenTracingOpenTracing数据模型 4. 使用分布式链路追踪的好处5. SkyWalking相关问题思考5.1 如何自动采集数据5.2 如何跨进程传递5.3 traceId如何保证全局唯一5.4 请求量大&#xff0c;采集数据对性能的影响 1. 总览 2. …

ES6 总结

概述 笔记内容为参考《JavaScript 高级程序设计 (第4版)》相关内容进行 ES6 部分知识的总结。主要涉及的知识是变量声明、对象解构、函数和对象的扩展内容、集合引用类型的扩展和面向对象编程等。 ES6 学习系列笔记 ES6 总结Symbol、Map、SetES6 中的类&#xff08;class&am…

LeetCode刷题集(三)(26 删除有序数组中的重复项)

学习目标&#xff1a; 基本掌握LeetCode中的26删除有序数组中的重复项 学习内容&#xff1a;LeetCode 26删除有序数组中的重复项 题目描述&#xff1a; 给你一个 升序排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c…

刘二大人《Pytorch深度学习实践》第十一讲卷积神经网络(高级篇)

文章目录 Inception-v1实现Skip Connect实现 Inception-v1实现 Inception-v1中使用了多个11卷积核&#xff0c;其作用&#xff1a; (1)在大小相同的感受野上叠加更多的卷积核&#xff0c;可以让模型学习到更加丰富的特征。传统的卷积层的输入数据只和一种尺寸的卷积核进行运算&…

windows系统本地批量预览svg图标

一、为何需要此操作 目前前端使用图标大致分为两类&#xff1a; iconfont方式&#xff1a;通过引入在线或者下载到本地的iconfont.css类文件实现显示图标第二类是封装图标组件&#xff0c;通过传入指定的svg名称快速生成图标 目前第二种是比较方便的&#xff0c;不需要频…

【记录】Truenas Scale|中危漏洞,需要SMB签名

部分内容参考&#xff1a;等保测试问题——需要SMB签名(SMB Signing not Required) 以及 ChatGPT。 Truenas常用SMB服务&#xff0c;但默认并不开启SMB签名。这样具有中间人攻击的风险。 一、漏洞详情 1.1 漏洞报告 漏洞提示如下&#xff1a; 1.2 漏洞介绍 SMB是一个协议名…

Mybatis-Plus -01 Mybatis-Plus入门

Mybatis-Plus入门 1 Mybatis-Plus1.1 Mybatis-Plus简介1.2 Mybatis-Plus特性1.3 Mybatis-Plus框架结构1.1 Mybatis-Plus简介1.2 Mybatis-Plus特性1.3 Mybatis-Plus框架结构 2 Mybatis-Plus 快速入门2.1 数据库准备2.2 导入mybatis-plus依赖2.3 Spring整合MP2.4 编写实体类2.5 编…

i.MX8MP平台开发分享(gicv3篇)-- set_handle_irq及中断路由过程分析

专栏目录&#xff1a;专栏目录传送门 平台内核i.MX8MP5.15.71 文章目录 set_handle_irqhard中断入口 set_handle_irq(gic_handle_irq);set_handle_irq 这个函数的功能很简单&#xff0c;将gic_handle_irq设置为中断处理函数。在发生中断异常后&#xff0c;内核就会切入到这个…

060201面积-定积分在几何学上的应用-定积分的应用

文章目录 1 平面图形的面积1.1 直角坐标情形1.2 极坐标情形1.2.1 极坐标的定义1.1.2 曲边扇形的面积 结语 1 平面图形的面积 1.1 直角坐标情形 ①平面图形由 y f ( x ) , y 0 , x a , y b yf(x),y0,xa,yb yf(x),y0,xa,yb围成图像的面积&#xff0c;如下图1.1-1所示&#…

防洪决策指挥系统(Axure高保真原型)

使用Axure制作的rp高保真原型防洪决策指挥系统可用于行业参考、实际业务需求开发、学习交流使用&#xff0c;本原型需求可以作为开发使用&#xff0c;业务需求均为作者本人行业经验。本系统包括水系展示系统、城区调度决策系统、实时监测预警和防洪调度四大功能模块的界面。 原…

MICCAI 2023 FLARE国际竞赛:打造腹部泛癌CT分割Foundation Models

竞赛官网 CodaLab - Competitionhttps://codalab.lisn.upsaclay.fr/competitions/12239 背景介绍 腹部器官是相当常见的患癌部位&#xff0c;例如结直肠癌和胰腺癌&#xff0c;分别位列癌症死亡率排名的第二位和第三位。Computed tomography (CT) 成像可以为医生提供重要的诊…

前端错误合集

Uncaught Reference Error: xx is not defined 未捕获的引用错误&#xff1a;未定义xx 原因 1.关键字写错了 解决办法 1.修改成正确的关键字 NAN 计算错误 原因 计算时数据类型不同 解决办法 使用数据类型相同的数据进行计算 Uncaught SyntaxError: Invalid left-h…

计算广告(十四)

营销是一个涉及产品、服务或品牌从概念到消费者的全过程的商业活动。它包括分析市场需求、识别潜在消费者、制定和实施策略以满足他们的需求、创造价值和实现销售。营销的目标是在满足客户需求的同时&#xff0c;实现企业的利润和业务增长。 营销涉及以下几个关键环节&#xf…

vim编辑器的使用介绍

文章目录 vim编辑器的使用介绍vim的缓存、恢复与打开时的警告信息vim的额外功能可视化区块多文件编辑多窗口功能vim的关键词补全功能vim环境设置与记录&#xff1a;~/.vimrc、~/.viminfovim的环境设置参数 vim常用的命令示意图 其他vim使用注意事项中文编码的问题DOS与Linux的换…