List-顺序表--2

目录

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);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通过串口通信控制led灯的亮灭

初始化led灯的gpio接口控制灯的亮灭 初始化uart1串口 将gpio9和gpio10设置为复用模式进行串口通信 通过串口的输入输出函数实现串口通信控制led灯的亮灭

git知识点汇总

git init 初始化一个git仓库&#xff0c;后面可以加仓库名&#xff0c;在当前目录下创建指定名称的目录并在该目录下创建仓库&#xff0c;若不加则直接在当前目录下创建仓库。git仓库的三个区域&#xff1a;工作区&#xff08;当前目录&#xff09;、暂存区&#xff08;.git/in…

电子电气架构 --- 中央HPC架构

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…

让 Agent 具备语音交互能力:技术突破与应用前景(16/30)

让 Agent 具备语音交互能力&#xff1a;技术突破与应用前景 一、引言 在当今数字化时代&#xff0c;人机交互方式正经历着深刻的变革。从早期的命令行界面到图形用户界面&#xff0c;再到如今日益普及的语音交互&#xff0c;人们对于与机器沟通的便捷性和自然性有了更高的追求…

L27.【LeetCode笔记】2 的幂(五种解法)

目录 1.题目 2.自解 方法1:调用log函数 代码 提交结果 方法2:循环 提交结果 3.优解 方法3:位运算n & (n-1) 0 代码 提交结果 方法4:位运算lowbit 代码 提交结果 4.投机取巧的方法 代码 提交结果 1.题目 https://leetcode.cn/problems/power-of-two/?env…

第0章 机器人及自动驾驶SLAM定位方法全解析及入门进阶学习建议

嗨&#xff0c;各位同学大家好&#xff01;笔者自985硕士毕业后&#xff0c;在机器人算法领域已经深耕 7 年多啦。这段时间里&#xff0c;我积累了不少宝贵经验。本专栏《机器人工程师带你从零入门SLAM》将结合下面的SLAM知识体系思维导图及多年的工作实战总结&#xff0c;将逐…

密码学原理技术-第十一章-Hash Functions

文章目录 总结Why we need hash functionsDigital Signature with a Hash FunctionBasic Protocol for Digital Signatures with a Hash FunctionPrincipal input–output behavior of hash functions Security propertiesThe three security requirements of hash functionsWh…

Docker 远程访问完整配置教程以及核心参数理解

Docker 远程访问完整配置教程 以下是配置 Docker 支持远程访问的完整教程&#xff0c;包括参数说明、配置修改、云服务器安全组设置、主机防火墙配置&#xff0c;以及验证远程访问的详细步骤。 1. 理解 -H fd:// 参数的作用&#xff08;理解了以后容易理解后面的操作&#xff…

单元测试3.0+ @RunWith(JMockit.class)+mock+injectable+Expectations

Jmockit使用笔记_基本功能使用Tested_Injectable_Mocked_Expectations_jmockit.class-CSDN博客 静态变量直接赋值就好&#xff0c;没必要mock了 测试框架Jmockit集合junit使用 RunWith(JMockit.class) 写在测试案例类上的注解 Tested 在测试案例中,写在我们要测试的类上…

vue数据请求通用方案:axios的options都有哪些值

Axios 是一个基于 promise 的 HTTP 库&#xff0c;可以用在浏览器和 Node.js 中。 在使用 Axios 发送请求时&#xff0c;可以通过传递一个配置对象来指定请求的各种选项。 以下是一些常用的 Axios 配置选项及其说明&#xff1a; 1.url: &#xff08;必需&#xff09;请求的 …

MySQL 08 章——聚合函数

聚合函数是对一组数据进行汇总的函数&#xff0c;输入的是一组数据的集合&#xff0c;输出的是单个值 MySQL中&#xff0c;目前不能对聚合函数进行嵌套 一、聚合函数介绍 &#xff08;1&#xff09;AVG和SUM函数 举例&#xff1a;只适用于数值类型的字段&#xff08;或变量…

JVM对象创建过程

1 类加载检查 jvm通过new指令开始创建对象jvm执行new指令时&#xff0c;首先通过指令参数从常量池中取到需要创建的类名检查该类是否被加载&#xff0c;解析&#xff0c;和初始化过如果没有&#xff0c;则执行类的加载过程new指令对应到java语言具体的操作为 new 关键字创建对象…

Outlook2024版如何回到经典Outlook

Outlook2024版如何回到经典Outlook 如果新加入一家公司&#xff0c;拿到的电脑&#xff0c;大概率是最新版的Windows, 一切都是新的。 如果不coding, 使用国产的foxmail大概就可以解决一切问题了。可惜老程序员很多Coding都是基于传统Outlook的&#xff0c;科技公司所有人都是I…

三甲医院等级评审八维数据分析应用(五)--数据集成与共享篇

一、引言 1.1 研究背景与意义 随着医疗卫生体制改革的不断深化以及信息技术的飞速发展,三甲医院评审作为衡量医院综合实力与服务水平的重要标准,对数据集成与共享提出了更为严苛的要求。在传统医疗模式下,医院内部各业务系统往往各自为政,形成诸多“信息孤岛”,使得数据…

Scala_【4】流程控制

第四章 分支控制if-else单分支双分支多分支返回值嵌套分支 For循环控制包含边界不包含边界循环守卫循环步长嵌套循环循环返回值 While循环Break友情链接 分支控制if-else 单分支 双分支 多分支 返回值 嵌套分支 For循环控制 Scala也为for循环这一常见的控制结构提供了非常多的…

Nginx - 整合lua 实现对POST请求的参数拦截校验(不使用Openresty)

文章目录 概述步骤 1: 安装 Nginx 和 Lua 模块步骤 2: 创建 Lua 脚本用于参数校验步骤 3: 配置 Nginx 使用 Lua 脚本写法二&#xff1a; 状态码写法三 &#xff1a; 返回自定义JSON复杂的正则校验 步骤 4: 测试和验证ngx.HTTP_* 枚举值 概述 一个不使用 OpenResty 的 Nginx 集…

医院机房运维:所有IT资源运行状态同一平台实时呈现

在当今数字化医疗高速发展的时代&#xff0c;医院的信息化系统已然成为保障医疗服务顺畅开展、守护患者生命健康的关键基础设施。以郑州人民医院为例&#xff0c;随着医疗业务不断拓展&#xff0c;其背后支撑的机房运维面临着诸多棘手难题。 传统的分散式人工维护模式&#xff…

AcWing练习题:油耗

给定一个汽车行驶的总路程&#xff08;km&#xff09;和消耗的油量&#xff08;l&#xff09;&#xff0c;请你求出汽车每消耗 1 升汽油可行驶多少公里路程。 输入格式 输入共两行&#xff0c;第一行包含整数 X&#xff0c;表示行驶总路程。 第二行包含保留一位小数的浮点数…

前后端规约

文章目录 引言I 【强制】前后端交互的 API请求内容响应体响应码II 【推荐】MVC响应体III【参考】IV 其他引言 服务器内部重定向必须使用 forward;外部重定向地址必须使用 URL 统一代理模块生成,否则会因线上采用 HTTPS 协议而导致浏览器提示“不安全”,并且还会带来 URL 维护…

Redis(二)value 的五种常见数据类型简述

目录 一、string&#xff08;字符串&#xff09; 1、raw 2、int 3、embstr 二、hash&#xff08;哈希表&#xff09; 1、hashtable 2、ziplist 三、list&#xff08;列表&#xff09; ​编辑 1、linkedlist 2、ziplist 3、quicklist&#xff08;redis 3.2后的列表内…