Java进阶06List集合泛型

news2025/1/11 21:06:28

Java进阶06 集合

一、集合及其体系结构

集合是一个长度可变的容器

1、集合的体系结构

1.1 单列集合
  • 单列集合使用add()方法添加集合元素,一次只能添加一个元素。

  • 单列集合均实现了Collection接口,该接口还有两个子接口List和Set。

    • List接口

      List集合的特点是存取有序、有索引、可以存储重复的;包含ArrayList、LinkedList两个集合

    • Set接口

      Set集合的特点是存取无序、没有索引、不可以存储重复的;包含TreeSet、HashSet、LinkedHashSet

1.2 双列集合
  • 双列集合使用put()方法添加集合元素,一次可以添加两个元素

  • 双列集合均实现了Map接口

  • 双列集合包括:TreeMap、HashMap、LinkedHashMap

二、Collection的使用

方法名说明
public boolean add(E e)把给定的对象添加到当前集合中,返回是否添加成功
public void clear()清空集合中所有的元素
public boolean remove(E e)把给定的对象在当前集合中删除,返回是否删除成功
public boolean contains(Object obj)判断当前集合中是否包含给定的对象
public boolean isEmpty()判断当前集合是否为空
public int size()返回集合中元素的个数/集合的长度

注意事项:

  • remove()、contains()底层都是依赖equals方法

  • clear()是清空集合中所有元素,不是销毁集合容器。清空后还是可以继续往集合中添加元素的

三、集合遍历方式(5种)

1、普通for循环

ArrayList<String> list = new ArrayList<>();
​
for (int i = 0; i < list.size(); i++) {
    String s = list.get(i);
}

2、迭代器遍历

2.1 Collection接口的方法
方法说明
public Iterator<E> iterator()获取遍历集合的迭代器对象
public boolean hasNext()判断集合中是否还有元素
public E next()取出集合中元素,并且将指针向后移动一位
2.2 迭代器遍历
public class CollectionDemo2 {
    public static void main(String[] args) {
        //多态创建集合容器,左边为接口引用,右边为实现类对象
        Collection<Student> c = new ArrayList<>();
        
        c.add(new Student("张三", 23));
        c.add(new Student("李四", 24));
        c.add(new Student("王五", 25));
        
        // 1. 获取迭代器  其实这句代码相当于 Iterator<Student> it = new Itr();
        Iterator<Student> it = c.iterator();
        // 2. 循环的判断, 集合中是否还有元素
        while (it.hasNext()) {
            // 3. 通过迭代器取出集合的元素
            Student stu = it.next();
            System.out.println(stu.getName() + "---" + stu.getAge());
            
            //这样调用会出现信息错乱!!!
            System.out.println(it.next().getName() + "---" + it.next().getAge());
        }
    }
}

注意:next()方法每调用一次,迭代器指针会后移一位,就会把不同集合元素的信息拼接到一起打印,为了避免这种信息错乱,建议在循环中,next()只调用一次

2.3 迭代器源码分析
private class Itr implements Iterator<E> {
    //定义游标,表示指针指向
    int cursor; 
    
    public boolean hasNext() {
        //判断指针值是否等于集合长度
        return cursor != size;    
    }  
    
    public E next() { 
        //定义i变量记录当前指针所指向的元素下标
        int i = cursor;        
        //指针后移
        cursor = i + 1;        
        //返回i队应下标所记录的元素值
        return (E) elementData[lastRet = i];   
    }
}

3、增强for循环

增强for循环是JDK5之后出现的,其内部原理就是一个Iterator迭代器,它简化迭代器的代码书写,是迭代器遍历的语法糖。

3.1 格式
for(元素的数据类型 变量名 : 数据或者集合){
}

快捷键 需要迭代的集合.for再回车

3.2 Demo
public class CollectionDemo3 {
    public static void main(String[] args) {
        Collection<Student> c = new ArrayList<>();
        c.add(new Student("张三", 23));
        c.add(new Student("李四", 24));
        c.add(new Student("王五", 25));
​
        //增强for循环遍历集合
        for (Student stu : c) {
            System.out.println(stu);
        }
​
        System.out.println("----------------------");
​
        //增强for循环遍历数组
        int[] nums = {11, 22, 33};
        for (int num : nums) {
            System.out.println(num);
        }
    }
}

注意细节:增强for循环遍历数组时,循环变量直接代表每一份元素,并不是下标。为了避免和出错和fori搞混,这个循环变量我们一般不会取名为i

4、foreach方法

//遍历集合
default void forEach(Consumer<? super I>action)

跟进源码后发现该方法需要的参数Consumer是一个接口类型,那么我们就要传入该接口的实现类对象,可以创建一个并传入。然而源码中验证该接口还是一个函数式接口,因此可以传入匿名内部类,还可以将其改写成Lambda表达式。

public class CollectionDemo4 {
    public static void main(String[] args) {
        Collection<Student> c = new ArrayList<>();
        c.add(new Student("张三",23));
        c.add(new Student("李四",24));
        c.add(new Student("王五",25));
​
        //匿名内部类写法
        c.forEach(new Consumer<Student>() {
            @Override
            public void accept(Student student) {
                System.out.println(student);
            }
        });
​
        //Lambda表达式写法
        c.forEach(s-> System.out.println(s));
    }
}

5、ListIterator遍历

继承了Iterator,是List集合派系所特有的迭代器,遍历方式与Iterator遍历类似,但也有其特殊之处:它内部含有hasPrevious()方法和previous()方法,可以配合使用进行倒序遍历,前提是必须要先正序遍历让指针移至最后,否则倒叙遍历没有效果

public static void main(String[] args) {
        List<String> list = new ArrayList<>();
​
        list.add("张三");
        list.add("李四");
        list.add("王五");
​
​
        ListIterator<String> it = list.listIterator();
​
        //正序遍历
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }
​
        System.out.println("---------------------------------");
​
        //倒序遍历,前提必须先正序遍历让指针后移至最后,否则没有效果
        while (it.hasPrevious()) {
            String s = it.previous();
            System.out.println(s);
        }
    }

四、List接口

list接口因为支持索引,所以多了很多索引操作的独特API

方法名说明
void add(int index,E element)在此集合中的指定位置插入指定的元素
E remove(int index)删除指定索引处的元素,返回被删除的元素
E set(int index,E element)修改指定索引处的元素,返回被修改的元素
E get(int index)返回指定索引处的元素

五、数据结构

数据结构是计算机底层存储组织数据的方式,是指数据相互之间是以什么方式排列在一起的

1、栈和队列

队列
一端开口(栈顶),一端封闭(栈底)两端均开口
栈顶出入栈队尾入队,队头出队
后进先出先进先出

2、数组和链表

数组链表
内存连续区域在内存中游离,不连续
查询速度快:通过地址和索引定位,查任意数据耗时相同查询速度慢:没有索引,无论查询哪个数据都要从头遍历
增删效率低:增删有可能大批量的移动数组中其他元素增删效率相对数组快:增删不用移动大量元素,只需修改指针即可
  • 单链表&双链表

链表元素在内存中是游离的,其中每个结点是独立的对象,在内存中不是连续的,每个结点有自己的存储地址,包含其存储的具体数据值和下一个结点的地址。见名知义,单链表即链接方向是单向的,对链表的访问要通过顺序读取从头部开始。双链表的链接方向是双向的,即每个数据结点中都有两个指针,分别指向直接后继和直接前驱。因此双向链表首尾操作极快!!!

六、ArrayList类&LinkedList类

1、ArrayList类

ArrayList底层是基于数组实现的,所以查询元素快,增删相对慢

1.1 ArrayList长度可变原理

ArrayList底层是数据结构,数组默认长度为10;当数组添加满了之后,会自动扩容为1.5倍,扩容时会先将原数组数据拷贝到新数组中,再将新元素添加到新数组

1.2 ArrayList源码解析

使用空参构造器创建的集合,在底层创建一个默认长度为0的数组

添加第一个元素时,底层会创建一个新的长度为10的数组

存满时,会扩容1.5倍

2、LinkedList类

LinkedList底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的

特有方法说明
public void addFirst(E e)在该列表开头插入指定的元素
public void addLast(E e)将指定的元素追加到此列表的末尾
public E getFirst()返回此列表中的第一个元素
public E getLast()返回此列表中的最后一个元素
public E removeFirst()从此列表中删除并返回第一个元素
public E removeLast()从此列表中删除并返回最后一个元素
  • 注意:LinkedList的get()方法,表面看起来是根据索引获取元素,实际并非如此。它的原理很简答,是通过遍历链表来查找指定索引的元素。具体来说,get()方法从链表的表头开始遍历,它经过一个节点,就将计数器加一。当计数器的值等于要查找的索引时,get()方法就返回该节点的元素值,否则继续遍历直到表尾。

七、泛型

JDK5引入泛型,可以在编译阶段约束操作的数据类型,并进行检查。使用泛型的好处是:统一数据类型,将运行期的错误提升到了编译期。泛型中只能编写引用型数据,如果不指定泛型的具体类型,则系统默认创建Object对象

1、泛型类

1.1 使用场景

当类中的属性或是方法却无法确定具体类型时,可以设计泛型类

1.2 确定具体类型

在创建对象的时候确定到具体数据类型

//泛型类
public class ArrayList<E>{
    private E e;
    public E getE(){
        return e;
    }
    public void setE(E e){
        this.e = e;
    }
}
​
public static void main(String[] args){
    //创建对象,指定类型为Integer
    Student<Integer> stu = new Student<>;
}

2、泛型方法

2.1 非静态泛型方法

泛型是根据类的泛型去匹配的

public class ArrayList<E>{
    public boolean add(E e){
    }
}
2.2 静态泛型方法

需要声明出自己独立的泛型

public static<T> void printArray(T[] array){}
public class Demo3 {
    public static void main(String[] args) {
        Integer[] arr1 = {11,22,33};
        Double[] arr2 = {11.1,22.2,33.3};
        String[] arr3 = {"张三","李四","王五"};
​
        printArray(arr1);
        printArray(arr2);
        printArray(arr3);
    }
​
    //该方法在main函数中调用,因此必须是static修饰,又想接收各种类型,所以自己定义独立的泛型
    private static<T> void printArray(T[] arr) {
        System.out.print("[");
        for (int i = 0; i < arr.length-1; i++) {
            System.out.print(arr[i]+",");
        }
        System.out.println(arr[arr.length-1]+"]");
    }
}

3、泛型接口

3.1 使用场景

接口中的某个抽象方法确定不了参数的具体类型,就可以声明泛型,让该方法的泛型去匹配接口的泛型

3.2 确定具体数据类型

类实现接口时,如果接口带有泛型,有两种操作方式

  • 类实现接口的时候,直接确定类型

  • 实现类延续接口的泛型,等创建对象的时候再确定

//泛型接口
interface Inter<E>{
    //抽象方法的参数匹配接口的泛型
    void show(E e);
}
​
//类实现接口的时候直接指定类型为String
class InterAImpl implements Inter<String>{
​
     @Override
     public void show(String s) {
​
     }
}
​
//实现类延用接口泛型,则在该实现类创建对象的时候一定要给出具体类型
class InterBImpl<E> implements Inter<E>{
​
     @Override
     public void show(E e) {
          
     }
}

4、泛型通配符

书写位置在<>内,有以下三种用法

  • :任意类型

  • ?extends E:只能接收E或者E的子类

  • ?super E:只能接收E或者E的父类

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

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

相关文章

详细分析McCabe环路复杂度(附例题)

目录 前言1. 基本知识2. 例题 前言 该知识点常出在408或者软考中&#xff0c;对此此文重点讲讲理论知识以及例题 对于例题平时看到也会更新 1. 基本知识 McCabe环路复杂度是一种用于衡量软件代码复杂性的指标&#xff0c;主要是通过计算代码中的控制流图中的环路数量来衡量…

为什么选择ATECLOUD自动化测试平台?

在当今飞速发展的时代&#xff0c;一切都在不断进步与变革&#xff0c;电测行业也由手动测试逐步转向了自动化测试。但是随着科技的发展&#xff0c;对于产品的测试要求也越来越高&#xff0c;传统的自动化测试系统已经无法满足用户日益增长的测试需求&#xff0c;全新的ATE测试…

全国33个省228189个矿产地位置分布数据,含经纬度坐标/CSV格式

全国矿产地分布&#xff08;2021版&#xff09; 数据来源&#xff1a; 全国矿产地数据库2021版 (ngac.org.cn) http://data.ngac.org.cn/mineralresource/index.html 数据获取方法&#xff1a;树谷资料库大全&#xff08;2024年4月19日更新&#xff09; 进入网站后&#xf…

【Qt 开发基础体系】Qt信号与槽机制

文章目录 1.Qt 信号与槽机制原理&#xff08;Signal & Slot&#xff09;2. QObject 类 connect 的介绍3. 信号与槽机制连接方式4. 信号和槽机制优势及其效率&#xff1a;3. 信号与槽机制应用 1.Qt 信号与槽机制原理&#xff08;Signal & Slot&#xff09; &#x1f42…

cesium雷达扫描(消逝圆效果)

cesium雷达扫描(消逝圆效果) 以下为源码直接复制可用 1、实现思路 通过修改“material”材质来实现轨迹球效果 2、示例代码 1、index.html <!DOCTYPE html> <html lang="en"><head><!

程序的机器级表示——Intel x86 汇编讲解

往期地址&#xff1a; 操作系统系列一 —— 操作系统概述操作系统系列二 —— 进程操作系统系列三 —— 编译与链接关系操作系统系列四 —— 栈与函数调用关系操作系统系列五 —— 目标文件详解操作系统系列六 —— 详细解释【静态链接】操作系统系列七 —— 装载操作系统系列…

漏扫神器Invicti V2024.4.0专业版

前言 Invicti Professional是Invicti Security公司推出的一个产品&#xff0c;它是一种高级的网络安全扫描工具。Invicti Professional旨在帮助组织发现和修复其网络系统中的潜在安全漏洞和弱点。它提供了全面的漏洞扫描功能&#xff0c;包括Web应用程序和网络基础设施的漏洞扫…

水库安全无忧,漫途智能监测方案守护大坝安全!

水库大坝作为水利工程的重要组成部分&#xff0c;不仅承担着防洪、蓄水、灌溉、发电等多重功能&#xff0c;同时也关系着人民群众的生命财产安全。 然而&#xff0c;随着时间的推移&#xff0c;许多水库大坝存在稳定性不足、渗漏现象严重、裂缝和断面不足等问题&#xff0c;安…

[C++]哈希应用-布隆过滤器快速入门

布隆过滤器 布隆过滤器&#xff08;Bloom Filter&#xff09;是一个由布隆在1970年提出的概率型数据结构&#xff0c;它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器的主要特点是高效的插入和查询&#xff0c;可以用于检索一个元素是否在一个集合中。 原理…

射频无源器件之耦合器

一. 耦合器的作用 在射频电路中,射频耦合器将一路微波功率按比例分成几路,用于检测或监测信号,如功率测量和波检测,还可改变信号的幅度、相位等特性,以满足不同的通信需求。根据输入与耦合端的功率差,常被分为5dB、6dB、10dB等耦合器。射频耦合器的类型主要包括定向耦合…

Infuse for Mac激活版:高清影音播放软件

对于热爱影音娱乐的Mac用户来说&#xff0c;Infuse for Mac是一个不容错过的选择。它以其简洁的操作界面和强大的播放功能&#xff0c;为用户带来了全新的影音播放体验。 Infuse for Mac支持广泛的音视频格式&#xff0c;无需额外转换&#xff0c;即可轻松播放您喜爱的影片。无…

2024年教育创新与人文艺术国际学术会议(ICEIHA 2024)

2024年教育创新与人文艺术国际学术会议(ICEIHA 2024) 2024 International Conference on Educational Innovation and Humanities and Arts 一、【会议简介】 2024年教育创新与人文艺术国际学术会议&#xff0c;将探讨教育创新与人文艺术的结合。 本次会议将汇集全球的专家学者…

使用idea管理docker

写在前面 其实idea也提供了docker的管理功能&#xff0c;比如查看容器列表&#xff0c;启动容器&#xff0c;停止容器等&#xff0c;本文来看下如何管理本地的docker daemon和远程的dockers daemon。 1&#xff1a;管理本地 双击shift&#xff0c;录入service&#xff1a; …

【3dmax笔记】026:挤出和壳修改器的使用

文章目录 一、修改器二、挤出三、壳 一、修改器 3ds Max中的修改器是一种强大的工具&#xff0c;用于创建和修改复杂的几何形状。这些修改器可以改变对象的形状、大小、方向和位置&#xff0c;以生成所需的效果。以下是一些常见的3ds Max修改器及其功能&#xff1a; 挤出修改…

C++学习————第十天(string的基本使用)

1、string 对象类的常见构造 (constructor)函数名称 功能说明&#xff1a; string() &#xff08;重点&#xff09; 构造空的string类对象&#xff0c;即空字符串 string(const char* s) &#xff08;重点&#xff09;…

二层交换机与防火墙连通上网实验

防火墙是一种网络安全设备&#xff0c;用于监控和控制网络流量。它可以帮助防止未经授权的访问&#xff0c;保护网络免受攻击和恶意软件感染。防火墙可以根据预定义的规则过滤流量&#xff0c;例如允许或阻止特定IP地址或端口的流量。它也可以检测和阻止恶意软件、病毒和其他威…

【linux软件基础知识】-死锁问题

死锁问题 当两个或多个线程由于每个线程都在等待另一个线程持有的资源而无法继续时,就会发生死锁 如下图所示, 在线程 1 中,代码持有了 L1 上的锁,然后尝试获取 L2 上的锁。 在线程 2 中,代码持有了 L2 上的锁,然后尝试获取 L1 上的锁。 在这种情况下,线程 1 已获取 L…

这个簇状柱形图怎么添加百分比?

这个图表是excel默认的图表配色&#xff0c;有的人做出来都那个百分比&#xff0c;一起来做一个这样的图表。 1.插入图表 选中数据区域&#xff0c;点击 插入选项卡&#xff0c;在图表那一栏&#xff0c;点一下柱形图右侧那个倒三角&#xff0c;在弹邮对话框中&#xff0c;选…

vivado刷题笔记46

题目&#xff1a; Design a 1-12 counter with the following inputs and outputs: Reset Synchronous active-high reset that forces the counter to 1 Enable Set high for the counter to run Clk Positive edge-triggered clock input Q[3:0] The output of the counter c…

26_Scala集合常用API汇总

文章目录 1.mkString2.size&#xff0c;length&#xff0c;isEmpty,contains3.reverse ,length,distinct4.获取数据相关4.1数据准备4.2准确获取尾部last4.3 除了最后一个元素不要其他都要4.4从集合获取部分数据 5.删除数据5.1删除3个从左边5.2删除3个右边 6.切分数据splitAt(n:…