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,一经查实,立即删除!

相关文章

WPF 简单绘制矩形

Canvas 画矩形&#xff1a; view和viewModel 绑定一起才显示移动轨迹&#xff08;可以定义一个string 看是否绑定属性的路径是正确的&#xff09; 前台&#xff08;绑定事件和显示移动的线&#xff09;&#xff1a; <Canvas Name"canvas" Background"#01FF…

Learn the architecture - Understanding Armv9-A trace

快速链接: . 👉👉👉 个人博客笔记导读目录(全部) 👈👈👈 付费专栏-付费课程 【购买须知】:【精选】ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈 — 适合小白入门【目录】ARMv8/ARMv9架构高级进阶-[目录]👈👈👈 — 高级进阶、小白勿买【加群】ARM/TEE…

json序列化时Long类型转换为String类型

将java对象序列化为json对象返回数据给前端时&#xff0c;js处理Long类型数据时会丢失精度&#xff0c;为了解决这种问题&#xff0c;往往给前端返回的Long类型数据要序列化为String类型&#xff0c;前面文章介绍过在springboot中的配置方式 json对象中对Long类型和String类型相…

四、虚拟机网络配置

目录 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…

【Android MediaCodec 将音频转换为 pcm 格式】

调用方法 var url "https://xxxx.mp3"DownloadAndConvertTask(context.cacheDir.path).execute(url)代码实现 class DownloadAndConvertTask constructor(cacheDirPath: String): AsyncTask<String?, Void?, Void?>() {//缓存路径var cacheDir File(cache…

【多线程】-- 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…

使用Docker本地部署chatgpt

GitHub上有一个开源的工程ChatGPT-Next-Web&#xff0c;这个工程已经封装好了UI以及和OpenAI的API之间的交互&#xff0c;你要做的事情就是把他部署到本地&#xff0c;并配置好你的OpenAI的sk&#xff0c;然后就可以使用了。那么接下来的文章里&#xff0c;我会手把手教你如何C…

Vue3 究竟好在哪里?

Vue3 相较于 Vue2 在很多方面都有所改进和优化&#xff0c;以下是一些主要的优点&#xff1a; 性能提升&#xff1a;Vue3 使用了新的编译器&#xff08;Vite&#xff09;&#xff0c;使得打包速度更快&#xff0c;运行速度也有所提升。同时&#xff0c;Vue3 对响应式系统进行了…

关于如何写好单元测试的思考

“二八定律”&#xff0c;由19世纪末20世纪初意大利经济学家巴莱多提出。他认为&#xff0c;在任何一组东西中&#xff0c;最重要的只占其中一小部分&#xff0c;约20%&#xff0c;其余80%尽管是多数&#xff0c;却是次要的。 What&#xff1f; 释义 单元测试&#xff08;uni…

C语言第四十弹---两个整数二进制位不同的个数

C语言求两个整数二进制位不同的个数 遍历法&#xff0c;使用循环获取每一位二进制位数&#xff0c;并让二进制位与1比较&#xff0c;如果相同则忽略&#xff0c;不同则个数增加。 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h>int main() {int a 0;int b 0;in…

4.求解无向图的各连通分支

求解无向图的各连通分支 输入&#xff1a; 第一行为图的节点数n&#xff08;节点编号0至n-1&#xff0c;0<n<10&#xff09; 从第二行开始列出图的边&#xff0c;-1表示输入结束 输出&#xff1a; 输出每个连通分支的广度优先搜索序列&#xff08;从连通分支的最小编号…

下拉列表select动态添加option和获取选中的option的值和value

分别用两种方法动态添加option&#xff1a; 方法一&#xff1a;JS方法添加 1、创建select标签 var select documnet.createElement(‘select’); 2、给select添加id select.setAttribute(‘id’,‘selectid’); 3、给select添加onchange事件 select.setAttribute(‘onc…

【云原生系列】Kubernetes知识点

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

如何解决Windows中“Address already in use: bind“错误

当在Windows系统中开发网络应用程序时&#xff0c;经常会遇到 "Address already in use: bind" 的错误。这个错误通常表示正在尝试绑定的端口已经被其他程序占用了。本篇技术博客将介绍如何在Windows系统中解决这个问题&#xff0c;并提供实用的解决方案。 在网络应用…

Axios.post 请求报错: 403 Forbidden missing csrf token 和 invalid csrf token

Axios.post 请求报错&#xff1a;403 Forbidden missing csrf token 和 invalid csrf token 问题及解决 这个问题是在一个 post 请求的跨域接口上出现的 很奇怪的问题&#xff0c;可以直接看一解决方案就行了 一、解决方案 问题&#xff1a;使用 Axios.post 请求报错&#xff…

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

文章目录 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 …

【JavaSE】Java基础(学习笔记)

一、数组 1、动态初始化 int arr new int[3];数组名字是地址默认初始值为0数组的内存分配 2、数组的内存分配 arr存在栈里&#xff0c;只存地址&#xff0c;是局部变量&#xff0c;相当于指针new出来的实体/对象存在堆里&#xff0c;存放数据&#xff0c;用完也不会立即消…