JAVA全栈开发 day14_集合(Collection\List接口、数据结构、泛型)

一、数组

数组是一个容器,可以存入相同类型的多个数据元素。

  • 数组局限性:

    ​ 长度固定:(添加–扩容, 删除-缩容)

    ​ 类型是一致的

对象数组 :

int[] arr = new int[5];

Student[] arr = new Student[5];

  Student[] arr = new Student[3];Student stu = new Student("张三",18);Student stu2 = new Student("李四",28);Student stu3= new Student("王老吉",38);arr[0] = stu;arr[1] = stu2;arr[2] = stu3;System.out.println(arr[0].name);
  //Object类型的数组,可以存放任意引用类型, 如果是基本类型,会自动装箱Object[] obj = new Object[5];obj[0] = new Student("赵四",18);obj[1] = new Teacher("杨老师",18);obj[2] = "abc";obj[3] = 111;obj[4] = true;

在这里插入图片描述

二、集合

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

  • 特点: 长度不固定,还可以存储不同的数据(但是一般都用同一类型)

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

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

  2. 数组中存储的是同一类型的元素,可以存储基本数据类型值。集合存储的都是对象。而且对象的类型可以不一致。在开发中一般当对象多的时候,使用集合进行存储。

1.集合的体系

在这里插入图片描述

2.Collection 常用的方法

2.1基本功能

  • public boolean add(E e): 把给定的对象添加到当前集合中 。
  • public void clear() :清空集合中所有的元素。
  • public boolean remove(E e): 把给定的对象在当前集合中删除。
  • public boolean contains(E e): 判断当前集合中是否包含给定的对象。
  • public boolean isEmpty(): 判断当前集合是否为空。
  • public int size(): 返回集合中元素的个数。
  • public Object[] toArray(): 把集合中的元素,存储到数组中。

2.2高级功能

  • boolean addAll(Collection<? extends E> c) 添加一个集合到当前集合
  • boolean removeAll(Collection<?> c) 移除一个集合元素
  • boolean retainAll(Collection<?> c) 两个集合都有的元素,思考元素去哪里?boolean又是什么意思?
  • boolean containsAll(Collection<?> c) 判断当前集合是否包含指定集合的元素 一个还是所有?

2.3集合的遍历

 public static void main(String[] args) {Collection c = new ArrayList();c.add("hello");c.add("java");c.add("collection");//遍历集合Object[] arr = c.toArray();//String -> Objectfor(int i=0;i<arr.length;i++){String s = (String)arr[i];System.out.println(s);}}

3.Iterator 迭代器

3.1迭代器的介绍

专门为集合提供遍历的一种技术

3.2迭代器的怎么使用

 Collection c = new ArrayList();Student student = new Student("张三",18);Student student2 = new Student("李四",28);Student student3 = new Student("王老吉",38);c.add(student);c.add(student2);c.add(student3);Iterator iterator = c.iterator();while (iterator.hasNext()){Student s = (Student) iterator.next();System.out.println(s);}

3.3迭代器的原理

在这里插入图片描述

三、数据结构

  • 数据结构的有什么用?

    数据结构:研究数据的存储

当你用着java里面的容器类很爽的时候,你有没有想过,怎么ArrayList就像一个无限扩充的数组,也好像链表之类的。好用吗?好用,这就是数据结构的用处,只不过你在不知不觉中使用了。

现实世界的存储,我们使用的工具和建模。每种数据结构有自己的优点和缺点,想想如果Google的数据用的是数组的存储,我们还能方便地查询到所需要的数据吗?而算法,在这么多的数据中如何做到最快的插入,查找,删除,也是在追求更快。

我们java是面向对象的语言,就好似自动档轿车,C语言好似手动档吉普。数据结构呢?是变速箱的工作原理。你完全可以不知道变速箱怎样工作,就把自动档的车子从 A点 开到 B点,而且未必就比懂得的人慢。写程序这件事,和开车一样,经验可以起到很大作用,但如果你不知道底层是怎么工作的,就永远只能开车,既不会修车,也不能造车。当然了,数据结构内容比较多,细细的学起来也是相对费功夫的,不可能达到一蹴而就。我们将常见的数据结构:堆栈、队列、数组、链表和红黑树 这几种给大家介绍一下,作为数据结构的入门,了解一下它们的特点即可。

1.常见的数据结构

数据存储的常用结构有:栈、队列、数组、链表和红黑树。我们分别来了解一下:

2.栈,队列

在这里插入图片描述

3.数组与链表

  • 数组: 利于查询 ,不利于增删改

  • 链表:不利于查询 ,利于增删改

    (根据需求,选择对应的数据形式,进行存储)

在这里插入图片描述

四、List 接口的方法

  • void add(int index, E element)

  • Object get(int index)

  • ListIterator listIterator()
    返回列表中的列表迭代器(按适当的顺序)。

  • Object set(int index, E element)
    用指定的元素(可选操作)替换此列表中指定位置的元素。

  • ListIterator listIterator() : 此方法重要;不但可以正向还可以反向,还可以进行添加和修改

在迭代器在迭代元素时,用集合去操作,出现以下的异常:

ConcurrentModificationException 并发修改异常

  • 解决方法
    ​ 迭代器在进行迭代元素时,就用迭代器去修改(包括添加)
    ​ 集合遍历元素时,就用集合去修改

1.List 子类特点

ArrayList类​         底层数组 : 查询快,增删改慢​         线程不安全: 不安全,效率高Vecktor类​         底层数组 : 查询快,增删改慢​         线程安全: 安全,效率低LinkedList类​        底层链表 : 查询慢,增删改快​         线程不安全: 不安全,效率高以上子类的选择,根据项目的需要来做 (看情况)

2.AarryList的方法使用

四种遍历

ArrayList list = new ArrayList();list.add("hello");list.add("world");list.add("java");//数组Object[] arr  = list.toArray();for(int i=0; i<arr.length;i++){String s = (String)arr[i];System.out.println(arr[i]);}//迭代器Iterator iterator = list.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}//列表迭代器ListIterator listIterator = list.listIterator();while (listIterator.hasNext()){System.out.println(listIterator.next());}//size  get()for(int i=0; i<list.size();i++){String s = (String)list.get(i);System.out.println(arr[i]);}

3.Vector类特有方法

  • addElement(E obj)
    将指定的组件添加到此向量的末尾,将其大小增加1。

  • elementAt(int index)
    返回指定索引处的组件。

  • elements()
    返回此向量的组件的枚举。

  • firstElement()
    返回此向量的第一个组件(索引号为 0的项目)。

JDK升级原因:

  1. 效率
  2. 简化书写
  3. 安全
  /** Vector类特有的方法* addElement(E obj) 将指定的组件添加到此向量的末尾,将其大小增加1。   add()elementAt(int index)返回指定索引处的组件。   get()elements() 返回此向量的组件的枚举。           iteratorhasMoreElements()                    hasNext()nextElement()                         next()firstElement() 返回此向量的第一个组件(索引号为 0的项目)。* */Vector vector = new Vector();vector.addElement("hello");vector.addElement("world");vector.addElement("java");//        for(int i=0;i<vector.size();i++){
//            System.out.println(vector.elementAt(i));
//        }
//        System.out.println(vector.firstElement());Enumeration enumeration = vector.elements();while (enumeration.hasMoreElements()){System.out.println(enumeration.nextElement());}

4.LinkedList类特有的方法

  • addFirst(E e)
    在该列表开头插入指定的元素。

  • addLast(E e)
    将指定的元素追加到此列表的末尾。

五、泛型

  • 泛型: 是一种把类型明确的工作推迟到创建对象或者调用方法的时候,才去明确的特殊类型, 参数化类型,把类型当做参数一样进行传递

  • 格式:
    <数据类型>
    此处数据类型只能是引用类型

  • 好处:

    1. 把运行时报的错误,提前到了编译期间
    2. 避免了强制转换
    3. 优化程序的设计,解决了黄色警告线

1.泛型的应用:

1.1类上定义泛型

   public class ObjectTool<T> {private T obj;public T getObj() {return obj;}public void setObj(T obj) {this.obj = obj;}}

1.2方法上定义泛型

在方法中定义泛型,相当于可以传任意类型的参数

    public <T> void show(T t){System.out.println(t);}

1.3接口上定义泛型

  • 方法1
 class MyListImpl implements MyList<String>{@Overridepublic void show(String s) {}
}
  • 方法2
 class MyListImpl<T> implements MyList<T>{@Overridepublic void show(T s) {}
}

2.泛型通配符

<?> : 任意类型 <? extends E> : 向下限定 , E及子类 <? supter E > : 向上限定 , E及父类 # 六、作业: 1.ArrayList去重复(新建集合,不新建集合); 2.用 LinkedList 类去模拟一个栈的集合类(add 方法,取方法 -- 先进后出) 3.使用Collection , ArrayList ,LinkedList, Vecktor 实现字符串集合的遍历 ,实现自定义对象的遍历 4.代码题 某中学有若干学生(学生对象放在一个List中),每个学生有一个姓名属性、年龄属性(int)、班级名称属性(String)和考试成绩属性(int), 某次考试结束后,每个学生都获得了一个考试成绩。请打印出所有学生分数总和,和平均年龄 # 七、面试题 ## 第一题:**List a=new ArrayList() 和 ArrayList a =new ArrayList()的区别?** ``` List list = new ArrayList(); 这句创建了一个 ArrayList 的对象后把上溯到了 List。此时它是一个List对象了,有些ArrayList 有但是 List 没有的属性和方法,它就不能再用了。 ArrayList list=new ArrayList(); 创建一对象则保留了ArrayList 的所有属性。所以需要用到 ArrayList 独有的方法的时候不能用前者。实例代码如下: List list = new ArrayList(); ArrayList arrayList = new ArrayList(); list.trimToSize(); //错误,没有该方法。 arrayList.trimToSize(); //ArrayList里有该方法。 ``` ## 第二题:**说一下ArrayList的扩容机制** ``` (1)带初始容量参数的构造函数,用户可以自己定义容量 (2)默认构造函数,使用初始容量10构造一个空列表(无参数构造) (3)构造包含指定collection元素的列表,这些元素利用该集合的迭代器按顺序返回 首先获取数组的旧容量,然后计算新容量的值,计算使用位运算,将其扩容至原来的1.5倍。 得到新容量的值后,校验扩容后的容量是否大于需要的容量,如果小于,则把最小需要容量当作扩容后的新容量。并确保扩容后的容量不超过数组能设置的最大大小值。 最后将老数组的数据复制到新的数组中。 ``` ## 第三题:Vector和ArrayList以及LinkedList区别和联系,以及分别的应用场景? Vector的底层的实现其实是一个数组,是线程安全的实现类,方法都有**synchronized** LinkedList的底层其实是一个**双向链表**,每一个对象都是一个Node节点,Node就是一个静态内部类,它是**线程不安全的,**所有的方法都没有加锁或者进行同步 这里先简单介绍一下,下面会对**ArrayList**的扩容机制进行分析 ArrayList是**线程不安全**的,如果不指定它的初始容量,那么它的初**始容量是0**,当**第一次**进行添加操作的时候它的容量将**扩容为10** **三种集合的使用场景** 1. Vector很少用,有其他线程安全的List集合 2. 如果需要大量的添加和删除则可以选择LinkedList 原因是:它查询的时候需要遍历整个链表,插入和删除的时候无需移动节点 3. 如果需要大量的查询和修改则可以选择ArrayList 原因:底层为数组,删除和插入需要移动其他元素,查询的时候根据下标来查 ## 第四题:我们想要使用线程安全的List集合,你有什么办法? 1:可以使用Vector 2.自己重写类似于ArrayList的但是线程安全的集合 3.可以使用**Collections(工具类)**中的方法,将ArrayList变成一个线程安全的集合 **4.可以使用java.util.concurrent包下的CopyOnWriteArrayList,它是线程安全的** ## 第五题:**那你说说CopyOnWriteArrayList是怎么实现线程安全的?** 它是juc包下的,专门用于并发编程的,他的设计思想是:**读写分离**,**最终一致,写时复制** **它不能指定容量,初始容量是0.它底层也是一个数组,集合有多大,底层数组就有多大,不会有多余的空间** **CopyOnWriteArrayList的缺点** 底层是数组,删除插入的效率不高,写的时候需要复制,占用内存,浪费空间,如果集合足够大的时候容易触发GC 数据一致性问题。CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。【当执行add或remove操作没完成时,get获取的仍然是旧数组的元素】。CopyOnWriteArrayList读取时不加锁只是写入和删除时加锁 应用场景:读操作远大于写操作的时候 **CopyOnWriteArrayList和Collections.synchronizedList区别** CopyOnWriteArrayList和Collections.synchronizedList是实现线程安全的列表的两种方式。两种实现方式分别针对不同情况有不同的性能表现,其中CopyOnWriteArrayList的写操作性能较差,而多线程的读操作性能较好。而Collections.synchronizedList的写操作性能比CopyOnWriteArrayList在多线程操作的情况下要好很多,而读操作因为是采用了synchronized关键字的方式,其读操作性能并不如CopyOnWriteArrayList。因此在不同的应用场景下,应该选择不同的多线程安全实现类。

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

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

相关文章

四、虚拟机网络配置

目录 1、VMware网卡配置模式 1.1 桥接模式 ​​​​​​​1.2 NAT模式 ​​​​​​​1.3 仅主机模式 ​​​​​​​2、编辑虚拟机的网络编辑器 ​​​​​​​3、编辑Window的虚拟网卡 ​​​​​​​4、修改IP地址为静态 4.1 查看网卡名字 4.2 编辑修改网卡IP地址的…

Vue中的组件和插件

一、组件 组件是Vue中最核心的概念之一&#xff0c;它可以把一个页面拆分成多个独立的、可复用的部分。组件通常包含了自己的模板、样式和逻辑&#xff0c;用于封装一个特定的功能或界面。Vue的组件有单文件组件和普通组件两种类型&#xff0c;可以通过Vue.component或Vue.ext…

【多线程】-- 07 线程礼让与线程强制执行

多线程 5 线程状态 5.3 线程礼让 Thread.yield()礼让线程&#xff0c;让当前正在执行的线程暂停&#xff0c;但不阻塞将线程从运行状态转为就绪状态让CPU重新调度&#xff0c;礼让不一定成功&#xff01;由CPU调度决定。 package com.duo.state;//测试礼让线程 public clas…

【2023CANN训练营第二季】——Ascend C算子调用及实验演示

自定义算子调用方式 完成自定义算子的开发部署后&#xff0c;可以通过单算子调用的方式来验证单算子的功能。单算子调用有API执行和模型执行两种方式&#xff1a; 单算子API执行&#xff1a;基于C语言的API执行算子&#xff0c;无需提供单算子描述文件进行离线模型的转换&…

leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

我的往期文章&#xff1a; leetCode 647.回文子串 动态规划 优化空间 / 中心扩展法 双指针-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/133883091?spm1001.2014.3001.5501leetCode 131.分割回文串 回溯算法 图解 笔记-CSDN博客https://blog.csdn.n…

【云原生系列】Kubernetes知识点

目录 概念 基础架构 单master节点 多master节点 组件 Master节点核心组件 其他组件 请求发送流程 插件 核心资源 调度资源 Pod 创建pod组件间调用流程 pod生命周期&#xff1a; 初始化容器 镜像拉取策略 重启策略 钩子函数 探针 探针的实现方式 DownwardAP…

数据收集与处理(爬虫技术)

文章目录 1 前言2 网络爬虫2.1 构造自己的Scrapy爬虫2.1.1 items.py2.1.2 spiders子目录2.1.3 pipelines.py 2.2 构造可接受参数的Scrapy爬虫2.3 运行Scrapy爬虫2.3.1 在命令行运行2.3.2 在程序中调用 2.4 运行Scrapy的一些要点 3 大规模非结构化数据的存储与分析4 全部代码 1 …

【EasyExcel实践】万能导出,一个接口导出多张表以及任意字段(可指定字段顺序)

文章目录 前言正文一、POM依赖二、核心Java文件2.1 自定义表头注解 ExcelColumnTitle2.2 自定义标题头的映射接口2.3 自定义有序map存储表内数据2.4 表头工厂2.5 表flag和表头映射枚举2.6 测试用的实体2.6.1 NameAndFactoryDemo2.6.2 StudentDemo 2.7 启动类2.8 测试控制器 三、…

数据结构-03-栈

1-栈的结构和特点 先进后出&#xff0c;后进先出 是栈的特点&#xff1b; 从图中&#xff0c;我们看到A入栈先放入底部&#xff0c;然后依次B和C&#xff1b;出栈的顺序依次是C-B-A&#xff1b;这种结构只能在一端操作。所以当某个数据集合只涉及在一端插入和删除数据&#xf…

什么是灯塔工厂?灯塔工厂的作用?

什么是灯塔工厂&#xff1f; "灯塔工厂"概念源于德国的工业4.0战略&#xff0c;又称“工业4.0示范工厂”或“标杆工厂”&#xff0c;代表工业领域顶级的智能制造能力。2018年&#xff0c;由世界经济论坛和麦肯锡共同推出。 灯塔工厂是通过数字化、网络化和智能化手…

Git常用命令#merge分支合并

要查看所有分支&#xff0c;包括本地和远程仓库的分支&#xff0c;可以使用以下命令&#xff1a; 1.查看分支 1.1 查看本地分支 git branch这个命令会列出本地所有的分支&#xff0c;当前所在的分支会有 * 标记。 1.2 查看远程分支 git branch -r这个命令会列出远程仓库的分…

Linux常用命令——pwd命令

文章目录 简介pwd命令的参数常见用法及实例1. 基本用法2. 使用 -P 参数3. 使用 -L 参数注意事项 结论 简介 pwd&#xff08;Print Working Directory&#xff09;是Linux和Unix系统中的一个常用命令&#xff0c;用于显示当前工作目录的完整路径。这个命令对于定位用户当前所在…

Vue3 刷新后,pinia存储的数据丢失怎么解决

这个问题有两种解决办法&#xff1a; 一是使用pinia的持久化存储一是使用vue的依赖注入 刷新后&#xff0c;通过pinia存储的vue store数据丢失&#xff0c;实际上是因为Vue原组件卸载、新组件重新挂载导致的&#xff0c;vue store是挂载在组件上的&#xff0c;当刷新导致组件…

C++调用python: VS2017 + Anaconda + pypi第三方库

步骤一&#xff1a;在Anaconda中创建虚拟环境 这一点对大家来说应该很简单&#xff0c;简单介绍一下&#xff0c;不做过多解释。值得注意的是&#xff0c;要用conda命令创建环境&#xff0c;用pip install配置环境。 conda create -n c_python_env python3.9 # 用conda创建pyt…

PyQt6 QToolButton工具按钮控件

​锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计32条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话…

服务器数据恢复—EMC存储raid5故障导致上层应用崩溃的数据恢复案例

服务器存储数据恢复环境&#xff1a; EMC某型号存储&#xff0c;8块组建一组raid5磁盘阵列。上层操作系统采用zfs文件系统。 服务器存储故障&分析&#xff1a; raid5阵列中有2块硬盘未知原因离线&#xff0c;raid5阵列崩溃&#xff0c;上层应用无法正常使用。 服务器数据恢…

Python实验项目8 :科学计算与可视化

1&#xff1a;创建 numpy 数组。 要求&#xff1a; &#xff08;1&#xff09;使用 array()函数、empty()函数、zeros()函数、linspace()函数等创建 numpy 数组。 &#xff08;2&#xff09;使用 numpy 数组的索引和切片方法访问数组元素。 # 要求&#xff1a; # &#xff0…

深度学习(三):pytorch搭建卷积神经网络

1.常用函数介绍 0 设备准备 device torch.device("cuda:0" if torch.cuda.is_available() else "cpu")这行代码是用来选择设备的&#xff0c;根据是否有可用的 CUDA 设备来选择使用 GPU 还是 CPU 进行计算。 更详细的解释如下&#xff1a; torch.cuda.…

socket.io介绍

1. 使用的技术 Socket.IO 是一个封装了 Websocket、基于 Node 的 JavaScript 框架&#xff0c;包含 client 的 JavaScript 和 server 的 Node。其屏蔽了所有底层细节&#xff0c;让顶层调用非常简单。 另外&#xff0c;Socket.IO 还有一个非常重要的好处。其不仅支持 WebSocket…

Spring三级缓存处理循环依赖的过程

Spring三级缓存 Spring三级缓存是什么&#xff1f; 一级缓存&#xff1a;单例池。存放的是完整的Bean对象。经过完整的生命周期。二级缓存&#xff1a;存放需要提前暴露的Bean对象。也就不完整的Bean对象。需要提前暴露就是指&#xff0c;可能会被循环依赖。(这里可能需要用代…