List-顺序表--2

news2025/1/8 16:20:49

目录

1、ArrayList

2、ArrayList构造方法

3、ArrayList常见方法

4、ArrayList的遍历

5、ArrayList的扩容机制

6、ArrayList的具体使用

6.1、杨辉三角

6.2、简单的洗牌算法


1、ArrayList

在集合框架中,ArrayList 是一个普通的类,实现了 List 接口

说明:

1. ArrayList是以泛型方式实现的,使用时必须要先实例化
2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
3. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
5. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList
6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

2、ArrayList构造方法

底层代码分析:

1. 带一个参数的构造方法,初始化 ArrayList 时可以指定初始容量

2. 不带参数的构造方法,初始化时分配的是一个空数组

既然没有分配内存,那这个 ArrayList 对象是如何存数据的呢?

^

继续查看 add 方法的原码,得出结论:

结论1:虽然初始化时没有分配内存,但是第一次 add 的时候会分配大小为10的内存

结论2:对于ArrayList来说,当容量满了,采用的扩容方式是1.5倍扩容

^

3. 有通配符的构造方法

参数列表的含义:

Collection:表示传入的参数是 Collection 类型的,实现了Collection接口的类型也可以

<? extends E>:通配符上界,这里表示可以传入的参数类型是 E 或者 E 的子类

^

例如:

ArrayList<Integer> list = new ArrayList<>();

ArrayList<Number> list1 = new ArrayList<>(list);

首先,list 是实现了 Collection 接口的,?:Integer ;E: Number,Integer 是 Number 的子类,list 满足这两个条件,所以可以作为参数正确执行。相当于把 list 表中数据打包给到 list

    public static void main(String[] args) {

        LinkedList<Integer> list1 = new LinkedList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);

        ArrayList<Number> list2 = new ArrayList<>(list1);
        list2.add(99);
        list2.add(88);

        System.out.println(list2); // 输出 [1,2,3,99,88]
    }

3、ArrayList常见方法

    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);

        ArrayList<Number> list123 = new ArrayList<>();
        list123.addAll(list); // 与上述第三个构造方法类似
        System.out.println(list123);//123

        list123.remove(2); // 删除 2 位置元素
        list123.remove(new Integer(2)); // 删除遇到的第一个 2
        System.out.println(list123);//23

        list123.get(0);
        list123.set(1,2);
        list123.contains(1);

        list.add(4);
        list.add(5);

        //并不会产生新的对象!
        List<Integer> list1 = list.subList(1,3); // [1,3)

        System.out.println(list1);
        System.out.println("==============");

        list1.set(0,99);
        System.out.println(list1);
        System.out.println(list);
    }

上述 subList 方法执行结果:

list1:  [99,3]

list:    [1, 99, 3,4, 5]

发现通过 list1 修改,list 也会发生改变,所以 subList 的执行过程并不会产生新的对象,在这个案例中,list1 的起始位置指向 list 的 1 下标

4、ArrayList的遍历

1. for循环+下标

public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    list.add(5);
    // 使用下标+for遍历
    for (int i = 0; i < list.size(); i++) {
        System.out.print(list.get(i) + " ");
    }
    System.out.println();
}

2. foreach

^

for(Integer x : list) {
    System.out.print(x+" ");

}
System.out.println();

3. 迭代器

只有实现了 literable 接口的类型,才能使用迭代器;Map 就不能使用,因为他没有实现 literable 接口

Iterator<Integer> it = list.iterator();    --  通用迭代器

Iterator<Integer> it = list.listIterator();    --  List 的专属迭代器

^

//使用 迭代器 遍历集合类 list
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
    System.out.println(it.next()+" ");

}

注意:ArrayList最长使用的遍历方式是:for循环+下标 以及 foreach 

5、ArrayList的扩容机制

在上述构造方法中,通过查看 add 方法的底层代码得出结论:ArrayList是一个动态类型的顺序表,即:在插入元素的过程中会自动扩容

底层代码总结:

1. 检测是否真正需要扩容,如果是调用grow准备扩容
2. 预估需要库容的大小

  • 初步预估按照1.5倍大小扩容
  • 如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容
  • 真正扩容之前检测是否能扩容成功,防止太大导致扩容失败

3. 使用copyOf进行扩容

6、ArrayList的具体使用

6.1、杨辉三角

力扣118

分析 List<List<Integer>> 

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> ret = new ArrayList<>();
        // 1. 先处理第一行
        List<Integer> list = new ArrayList<>();
        list.add(1);
        ret.add(list);
        // 2. 从第2行开始计算 每个list当中的数据
        for(int i = 1;i < numRows;i++) {
            // 3. 先准备当前行数据
            List<Integer> curRow =  new ArrayList<>();
            // 4. 准备当前行的第一个数据
            curRow.add(1);
            // 5. 准备当前的中间数据
            List<Integer> prevRow = ret.get(i-1); // 拿到上一行的数据
            for(int j = 1; j < i;j++) {
                // 上一行的当前列 + 上一行的前一列
                int val = prevRow.get(j) + prevRow.get(j-1);
                curRow.add(val);
            }
            // 6. 准备当前行最后一个数据
            curRow.add(1);
            // 7. 把这个数据放到二维数组当中去
            ret.add(curRow);
        }
        return ret;
    }
}

6.2、简单的洗牌算法

实现这个算法要解决的问题:

1.买一副牌【要生成一副扑克牌】放到哪里?

2.洗牌,怎么洗?

3.揭牌,每个人轮流抓5张牌,怎么抓牌?抓的牌放到哪里?

1. 创建一个 card 类,定义 花色 和 数字 两个属性;生成 get 和 set 方法;生成toString方法

package card;

public class Card {
    private String suit;//花色
    private int rank;//数字

    public Card(String suit, int rank) {
        this.suit = suit;
        this.rank = rank;
    }

    public String getSuit() {
        return suit;
    }

    public void setSuit(String suit) {
        this.suit = suit;
    }

    public int getRank() {
        return rank;
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    @Override
    public String toString() {
        return suit+":"+rank+" ";
    }
}

2. 创建 CardDemo 和 Test 类;CardDemo类中定义一个买牌的方法,在Test类中测试

    一共52张牌 1-k,其中1对应A、J对应11、Q对应12、K对应13

 3. 在CardDemo 类中再定义一个花色类,并完善buyCard方法

4. 买完牌后洗牌,这里使用生成随机数的方式,从最后一张牌开始,与随机生成的牌交换

5. 揭牌,3个人每人轮流揭5张,每次揭1张

把三个人的关系用一个二维数组表示

每揭一张牌,就把整副牌的0下标位置删除

CardDemo 类的完整代码

public class CardDemo {

    private  final String[] suits = {"♥","♠","♦","♣"};

    /**
     * 52张 1-K
     *      J   Q  K
     *      11 12 13
     * @return
     */
    public List<Card> buyCard() {
        List<Card> cardList = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            for (int j = 1; j <= 13; j++) {
                Card card = new Card(suits[i],j);
                cardList.add(card);
            }
        }
        return cardList;
    }

    public void shuffle(List<Card> cardList) {
        Random random = new Random();
        for (int i = cardList.size()-1; i > 0; i--) {
            int index = random.nextInt(i);
            //index  i 交换
            swap(cardList,i,index);
        }
    }
    private void swap(List<Card> cardList,int a,int b) {
        Card tmp = cardList.get(a);
        cardList.set(a,cardList.get(b));
        cardList.set(b,tmp);
        /**
         * tmp = a
         * a = b
         * b = tmp
         */
    }

    /**
     * 揭牌
     * 3个人 每个人轮流揭牌5张
     * @param cardList
     */
    public void getCard(List<Card> cardList) {

        List<Card> hand1 = new ArrayList<>();
        List<Card> hand2 = new ArrayList<>();
        List<Card> hand3 = new ArrayList<>();

        List<List<Card>> hands = new ArrayList<>();
        hands.add(hand1);
        hands.add(hand2);
        hands.add(hand3);

       //3个人 轮流抓牌5张 每次揭牌1张
        for (int i = 0; i < 5; i++) {
            //j代表人
            for (int j = 0; j < 3; j++) {
                Card card = cardList.remove(0);
                hands.get(j).add(card);
            }
        }

        System.out.println("第1个揭牌如下:");
        System.out.println(hand1);
        System.out.println("第2个揭牌如下:");
        System.out.println(hand2);
        System.out.println("第3个揭牌如下:");
        System.out.println(hand3);
        System.out.println("剩下的牌:");
        System.out.println(cardList);
    }
}

Test 类中代码

public class Test {
    public static void main(String[] args) {
        CardDemo cardDemo = new CardDemo();
        List<Card> cardList =  cardDemo.buyCard();
        System.out.println("买的牌如下:");
        System.out.println(cardList);

        System.out.println("洗牌:");
        cardDemo.shuffle(cardList);
        System.out.println(cardList);

        System.out.println("揭牌:");
        cardDemo.getCard(cardList);
    }
}

7、顺序表的优缺点

缺点:

  1. 插入数据必须移动其他数据,最坏情况下,就是插入到0位置。时间复杂度O(N)
  2. 删除数据也需要移动数据,最坏情况下,就是删除0位置。时间复杂度O(N)
  3. 扩容之后有可能会浪费空间

优点:在给定下标进行查找的时候,时间复杂度O(1)

总结:顺序表比较适合进行给定下标查找的场景。

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

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

相关文章

【C++】字符数|组的输出详解与拓展

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;字符数组的输出&#xff1a;三种方法解析方法1&#xff1a;直接输出字符串代码示例解析与特点 方法2&#xff1a;使用while循环逐字符输出代码示例解析与特点 方法3&#x…

解决iNodeClient客户端出现查询SSL VPN网关参数失败的问题

一、问题&#xff1a; 使用iNodeClient连接VPN报错&#xff0c;校验网关、用户名、密码都没问题&#xff0c;仍然抱错查询SSL VPN网关参数失败&#xff0c;请检查网络配置或联系管理员。 二、解决方案&#xff1a; 2.1 方案一 重启iNodeAuthService服务 sudo /Library/Star…

数树数(中等难度)

题目&#xff1a; 解题代码&#xff1a; n,qmap(int,input().split())#分别输入层数和路径数量 for i in range(q):sinput()#输入“L”或“R”x1for j in s:if j "L":xx*2-1 #&#xff01;&#xff01;&#xff01;规律else:xx*2print(x)

CAN201 Introduction to Networking(计算机网络)Pt.5 网络安全

文章目录 6. Network Security&#xff08;网络安全&#xff09;6.1 What is network security&#xff08;什么是网络安全&#xff09;6.2 Principles of cryptography&#xff08;密码学的原则&#xff09;6.2.1 Breaking an encryption scheme&#xff08;破解加密方案&…

【ArcGIS Pro二次开发实例教程】(2):BSM字段赋值

一、简介 一般的数据库要素或表格都有一个BSM字段&#xff0c;用来标识唯一值。 此工具要实现的功能是&#xff1a;按一定的规律&#xff08;前缀中间的填充数字OBJECT码&#xff09;来给BSM赋值。 主要技术要点包括&#xff1a; 1、ProWindow的创建&#xff0c;Label,Comb…

ros2笔记-2.5.3 多线程与回调函数

本节体验下多线程。 python示例 在src/demo_python_pkg/demo_python_pkg/下新建文件&#xff0c;learn_thread.py import threading import requestsclass Download:def download(self,url,callback):print(f线程&#xff1a;{threading.get_ident()} 开始下载&#xff1a;{…

C语言练习:求数组的最大值与最小值

文章目录 1. 提出任务2. 完成任务2.1 方法一&#xff1a;通过返回结构体指针来间接返回结果2.1.1 编写程序&#xff0c;实现功能2.1.2 运行程序&#xff0c;查看结果 2.2 方法二&#xff1a;通过参数传递数组&#xff0c;并在函数中修改传入的参数2.2.1 编写程序&#xff0c;实…

conda安装及demo:SadTalker实现图片+音频生成高质量视频

1.安装conda 下载各个版本地址&#xff1a;https://repo.anaconda.com/archive/ win10版本&#xff1a; Anaconda3-2023.03-1-Windows-x86_64 linux版本&#xff1a; Anaconda3-2023.03-1-Linux-x86_64 Windows安装 环境变量 conda -V2.配置conda镜像源 安装pip conda…

【前端系列01】优化axios响应拦截器

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、axios响应拦截器&#xff1a;☀️☀️☀️2.1 为什么前端需要响应拦截器element ui的消息组件 一、前言&#x1f680;&#x1f680;&#x1f680; ☀️ 回报不在行动之后&#xff0c;回报在行动之中。 这个系列可…

PingCAP 连续两年入选 Gartner 云数据库管理系统魔力象限“荣誉提及”

近日&#xff0c;全球 IT 市场研究和咨询公司 Gartner 发布最新报告《Magic Quadrant™ for Cloud Database Management Systems》&#xff08;云数据库管理系统魔力象限&#xff09;&#xff0c;PingCAP 因其企业级开源分布式数据库 TiDB 在全球市场的表现&#xff0c;连续两年…

CSS——2.书写格式一

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head><body><!--css书写中&#xff1a;--><!--1.css 由属性名:属性值构成--><!--style"color: red;font-size: 20px;&quo…

QT上实现SVM进行数据分类

针对不了解SVM的原理的同学强推下面这个课程&#xff1a; 6.机器学习课程&#xff08;六&#xff09;支持向量机&#xff08;线性模型&#xff09;问题_哔哩哔哩_bilibili 一、QT实现SVM的方法 1.调用SVM的C语言库&#xff1a;麻烦&#xff0c;要专门去找库&#xff0c;cmak…

idea( 2022.3.2)打包报错总结

一 报错 class lombok.javac.apt.LombokProcessor (in unnamed module 0x4fe64d23) cannot access class com.sun.tools.javac.processing.JavacProcessingEnvironment (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.processing …

极客说|微软 Phi 系列小模型和多模态小模型

作者&#xff1a;胡平 - 微软云人工智能高级专家 「极客说」 是一档专注 AI 时代开发者分享的专栏&#xff0c;我们邀请来自微软以及技术社区专家&#xff0c;带来最前沿的技术干货与实践经验。在这里&#xff0c;您将看到深度教程、最佳实践和创新解决方案。关注「极客说」&am…

解决 IntelliJ IDEA 中 Tomcat 日志乱码问题的详细指南

目录 前言1. 分析问题原因2. 解决方案 2.1 修改 IntelliJ IDEA 的 JVM 选项2.2 配置 Tomcat 实例的 VM 选项 2.2.1 设置 Tomcat 的 VM 选项2.2.2 添加环境变量 3. 进一步优化 3.1 修改 Tomcat 的 logging.properties3.2 修改操作系统默认编码 3.2.1 Windows 系统3.2.2 Linux …

某小程序sign签名参数逆向分析

文章目录 1. 写在前面2. 接口分析3. 分析还原 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…

医学图像分析工具02:3D Slicer || 医学影像可视化与分析工具 支持第三方插件

3D Slicer 是一款功能全面的开源医学影像分析软件&#xff0c;广泛应用于影像处理、三维建模、影像配准和手术规划等领域。它支持多种医学影像格式&#xff08;如 DICOM、NIfTI&#xff09;和丰富的插件扩展&#xff0c;是神经科学、放射学和生物医学研究中不可或缺的工具。 在…

Linux系统安装es详细教程

一、下载es及插件 从下面的网址进行对应es版本的下载https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.15.2-linux-x86_64.tar.gz &#xff0c;想要不同版本的es只需更换对应的版本号即可。 插件下载地址&#xff08;ik分词器、pinyin等&#xff09;es…

电子电气架构 --- 汽车总线基础介绍

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 简单&#xff0c;单纯&#xff0c;喜欢独处&#xff0c;独来独往&#xff0c;不易合同频过着接地气的生活…

安装PyQt5-tools卡在Preparing metadata (pyproject.toml)解决办法

为了在VS code中使用PyQt&#xff0c;在安装PyQt5-tools时总卡在如下这一步 pyqt5 Preparing metadata (pyproject.toml)经过各种尝试&#xff0c;最终问题解决&#xff0c;在此记录方法。 首先进入PyQt5-tools官网查看其适配的Python版本&#xff0c;网址如下&#xff1a; h…