百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

张小飞的Java之路——第三十一章——List

bigegpt 2024-10-12 06:08 7 浏览

写在前面:

视频是什么东西,有看文档精彩吗?

视频是什么东西,有看文档速度快吗?

视频是什么东西,有看文档效率高吗?

1. 介绍

张小飞:我看 List 也是一个接口

诸小亮:是的,它是 Collection 下最常用的子接口之一,有自己独有的特点

  • List:列表容器
  • 存储的元素是有序的(存储的顺序和取出的顺序一致)
  • 每个元素都有对应的下标,类似数组,所以可以通过下标获取元素
  • 允许存储重复元素

张小飞:原来如此,那么它都有哪些实现类呢?

诸小亮:按照数据结构(存储数据的方式)划分,它的实现类有3个:

  • ArrayList:最经常用的子类,底层使用可变数组存储数据
  • LinkedList:底层使用链表存储数据
  • Vector:底层也是可变数组,但不常使用,因为效率比 ArrayList 低


2. List的特有方法

张小飞:我们刚才用的就是 ArrayList

诸小亮:是的,不过,在讲解它的实现类之前,我们先看一下 List 接口的特有方法

1. add(int index, E e)

add(int index, E e):往指定位置插入元素,比如:

public static void main(String[] args) throws Exception {
    List list = new ArrayList();
    list.add("王昭君");
    list.add("甄姬");
    list.add(0,"嫦娥");//往指定位置添加元素,0表示第一个位置
    System.out.println(list);
}

结果:


张小飞:这个参数 E 是什么意思?

诸小亮:这时泛型的意思,我们之后会详细解释的


2. remove(int index)

remove(int index):删除指定位置的元素,并返回这个元素

结果:


3. get(int index)

get(int index):获取指定位置的元素,经常使用


结果:


张小飞:如果指定的 index 不存在呢?

诸小亮:跟数组一样,会报异常,比如:


结果:


4. set(int index, E e)

set(int index, E e):修改指定位置的元素

结果:


5. for循环

诸小亮:List 类型的集合,可以使用 for 循环遍历,比如:

public static void main(String[] args) throws Exception {
    ArrayList list = new ArrayList();
    list.add("王昭君");
    list.add("甄姬");
    list.add(0,"嫦娥");
    for(int i =0;i<list.size();i++){// 经常使用
        System.out.println(list.get(i));
    }
}

张小飞:原来还可以这样,我正想说用那个 Iterator 很不方便呢

诸小亮:确实,所以工作用我们一般都用 for 循环


6. ListIterator

诸小亮:ListIterator 是 List 集合的特有迭代器

张小飞:不是已经有 Iterator 了吗,怎么又来一个?


诸小亮:这式因为,在使用迭代器遍历 List 的时候,不能添加或删除元素,比如:

结果:


诸小亮:如果使用 List 特有迭代器就没问题

结果:

3. ArrayList

诸小亮:接下来我们介绍ArrayList——最常使用的列表容器

张小飞:看名字就知道,它的底层是数组结构

1. 可变数组

诸小亮:不错,它最大的特点就是——底层是可变数组

张小飞:数组有默认长度吧

诸小亮:是的,创建 ArrayList 对象时,其数组的默认长度是10


张小飞:我记得用可变数组——就是在数组存满后会创建一个新的更大的数组?

诸小亮:你说的不错,因此从指定位置插入和删除元素时候,要移动后面的所有元素,导致速度较慢

张小飞:既然这么慢,为什么您说 ArrayList 是最常用的列表容器呢?

诸小亮:因为它通过下标获取元素的速度非常块,工作中大多数都是读,而不是写

张小飞:明白了


诸小亮,还有一点,因为是可变数组,所以会自动扩容

张小飞:嗯嗯,这个我明白

诸小亮:重点是——扩容就是创建一个新的数组,是原来数组长度的 1.5 倍

2. 多线程

诸小亮:需要注意,ArrayList方法不是同步的,所以多线程操作是不安全的

张小飞:明白,就是跟 StringBuilder 差不多

诸小亮,额。。。,是有些类似

3. 存储重复元素

诸小亮:另外, List 是可以存储重复元素的

结果:


张小飞:难道还有其他的不能存储重复元素?

诸小亮:是的,我们之后会讲到


4. 操作自定义对象

诸小亮:之前操作的都是一些基本类型对象,下面我们操作自定义对象,比如:

class Hero {
    String name;
) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

public class StringDemo {
    public static void main(String[] args) throws Exception {
        ArrayList list = new ArrayList();
        //1. 存储自定义对象
        list.add(new Hero("西施"));
        list.add(new Hero("嫦娥"));
        list.add(new Hero("甄姬"));
        //2. 循环获取每个对象
        for(int i =0;i<list.size();i++){
            Hero hero = (Hero) list.get(i);//默认获取的是Object类型,需要向下转型
            System.out.println(hero.getName());
        }
    }
}

结果:


诸小亮,另外,获取元素时,也可以使用增强 for 循环

张小飞:操作自定义对象跟操作其他对象,没什么区别啊

诸小亮:是的

张小飞:那为什么要单独举个例子呢?

诸小亮:因为我们下面会用到

5. 去除重复元素

诸小亮:因为 ArrayList 可以存储重复元素,所以去重是工作中非常常见的场景

张小飞:这还不简单,它不是有个 contains 方法吗?用这个方法就可以了判断是否有重复元素了

class Hero {
    String name;

    public Hero(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //复写 equals 方法,判断两个Hero对象是否一样
    public boolean equals(Object obj){
        if(obj instanceof Hero){
            // 如果 name 一样,就认为 两个 hero 对象相同
            return this.getName().equals(((Hero)obj).getName());
        }
        return false;
    }

    @Override
    public String toString() {
        return "Hero{" +
                "name='" + name + '\'' +
                '}';
    }
}

public class StringDemo {
    public static void main(String[] args) throws Exception {
        ArrayList list = new ArrayList();
        list.add(new Hero("西施"));
        list.add(new Hero("妲己"));
        list.add(new Hero("嫦娥"));
        list.add(new Hero("甄姬"));
        list.add(new Hero("女娲"));
        list.add(new Hero("芈月"));
        list.add(new Hero("妲己"));
        list.add(new Hero("甄姬"));

        //去重
        getSingelElement(list);
        System.out.println(list);
    }

    private static void getSingelElement(ArrayList list) {
        //1. 创建一个新的列表存储不重复的元素
        ArrayList newList = new ArrayList();
        newList.add(list.get(0));
        for (int i = 1; i < list.size(); i++) {
            //2. 判断newList是否包含指定元素,如果不包含就存起来
            Hero hero = (Hero) list.get(i);
            if(newList.contains(hero)){
                //contains内部会调用元素的equals方法,判断你是否一样,所以Hero中要定义equals方法
                continue;
            }
            newList.add(hero);
        }
        list.clear();//清空老的数据
        list.addAll(newList);//放入新的数据
    }
}

诸小亮:不错,没想到你还真是考虑到在 Hero 中复写 equals 方法了

张小飞:嘿嘿,您之前不是说过嘛,contains 的内部就是调用了元素的 equals 方法

4. LinkedList

诸小亮:接着,我们说LinkedList——也是 List 接口的具体实现类之一,但工作中使用不是很多

1. 链表

张小飞:LinkedList 底层也是用的数组吗?

诸小亮:非也,LinkedList 底层使用的是链表

  • 链表是一种数据结构:前面节点存储着下一个节点的地址,比如:

张小飞:这么说,只要拿到第一个节点,就能获取之后的所有节点了,

诸小亮:不错,不过这只是:单向链表,而 LinkedList 底层是双向链表

张小飞:什么是双向链表?

诸小亮:来,看下面这个图

张小飞:明白了,就是每个元素不仅存放着下一个元素的地址,也存放着前一个元素的地址

诸小亮:没错,因为这种特性所以链表在插入和删除的时候,效率很高,比如:

张小飞:嗯嗯,确实,插入时只需要修改 next 属性就行了


张小飞:不过,LinkedList 的 get() 方法效率应该很慢比 ArrayList 慢

诸小亮:是的,比如 get(5),就意味着从头节点开始不断的向后找5次,才能获取到对应的数据

诸小亮:另外,链表跟数组最大的区别:数组在内存中是一块儿连续的内存,链表不是

张小飞:明白


诸小亮:LinkedList 还有一些其他特点,作为了解

  • 可以存储重复元素
  • 多线程下也是不安全的


2. 特有方法

诸小亮:LinkedList 也有一些自己特有的方法

1. addFirst

addFirst:把元素当成头节点加入链表中

public static void main(String[] args) throws Exception {
    LinkedList list = new LinkedList();
    list.add(new Hero("西施"));
    list.add(new Hero("妲己"));
    list.addFirst(new Hero("嫦娥"));//把 嫦娥 作为头节点

    System.out.println(list.getFirst());//获取头节点
}

结果:

2. removeFirst

removeFirst:删除头节点,并返回头节点元素

结果:

3. 遍历

诸小亮:因为 get(int index) 方法的效率很差,所以不推荐使用一般的 for 循环

张小飞:那,使用 Iterator 吗?

诸小亮:no,no,no,可以用 增强 for 循环

张小飞:这是为什么呢?

诸小亮:使用普通 for 循环就是根据下标获取元素,之前已经说了,效率很慢

张小飞:使用增强 for 循环就快了?

诸小亮:是的,而使用增强 for 循环不需要下标,而且更加简洁、易读

张小飞:明白了

诸小亮:但是,增强 for 循环在遍历时,无法对容器进行修改操作否则报错,你可以尝试一下

5. Vector

张小飞:这个 Vector 是???

诸小亮:Vector 是最早的一个集合类,底层也是可变数组

张小飞:这不是跟 ArrayList 一样吗?

诸小亮:非也,Vector 中都是同步方法,所以 ArrayList 是它的替代品

张小飞:原来如此

相关推荐

Go语言泛型-泛型约束与实践(go1.7泛型)

来源:械说在Go语言中,Go泛型-泛型约束与实践部分主要探讨如何定义和使用泛型约束(Constraints),以及如何在实际开发中利用泛型进行更灵活的编程。以下是详细内容:一、什么是泛型约束?**泛型...

golang总结(golang实战教程)

基础部分Go语言有哪些优势?1简单易学:语法简洁,减少了代码的冗余。高效并发:内置强大的goroutine和channel,使并发编程更加高效且易于管理。内存管理:拥有自动垃圾回收机制,减少内...

Go 官宣:新版 Protobuf API(go pro版本)

原文作者:JoeTsai,DamienNeil和HerbieOng原文链接:https://blog.golang.org/a-new-go-api-for-protocol-buffer...

Golang开发的一些注意事项(一)(golang入门项目)

1.channel关闭后读的问题当channel关闭之后再去读取它,虽然不会引发panic,但会直接得到零值,而且ok的值为false。packagemainimport"...

golang 托盘菜单应用及打开系统默认浏览器

之前看到一个应用,用go语言编写,说是某某程序的windows图形化客户端,体验一下发现只是一个托盘,然后托盘菜单的控制面板功能直接打开本地浏览器访问程序启动的webserver网页完成gui相关功...

golang标准库每日一库之 io/ioutil

一、核心函数概览函数作用描述替代方案(Go1.16+)ioutil.ReadFile(filename)一次性读取整个文件内容(返回[]byte)os.ReadFileioutil.WriteFi...

文件类型更改器——GoLang 中的 CLI 工具

我是如何为一项琐碎的工作任务创建一个简单的工具的,你也可以上周我开始玩GoLang,它是一种由Google制作的类C编译语言,非常轻量和快速,事实上它经常在Techempower的基准测...

Go (Golang) 中的 Channels 简介(golang channel长度和容量)

这篇文章重点介绍Channels(通道)在Go中的工作方式,以及如何在代码中使用它们。在Go中,Channels是一种编程结构,它允许我们在代码的不同部分之间移动数据,通常来自不同的goro...

Golang引入泛型:Go将Interface「」替换为“Any”

现在Go将拥有泛型:Go将Interface{}替换为“Any”,这是一个类型别名:typeany=interface{}这会引入了泛型作好准备,实际上,带有泛型的Go1.18Beta...

一文带你看懂Golang最新特性(golang2.0特性)

作者:腾讯PCG代码委员会经过十余年的迭代,Go语言逐渐成为云计算时代主流的编程语言。下到云计算基础设施,上到微服务,越来越多的流行产品使用Go语言编写。可见其影响力已经非常强大。一、Go语言发展历史...

Go 每日一库之 java 转 go 遇到 Apollo?让 agollo 来平滑迁移

以下文章来源于GoOfficialBlog,作者GoOfficialBlogIntroductionagollo是Apollo的Golang客户端Apollo(阿波罗)是携程框架部门研...

Golang使用grpc详解(golang gcc)

gRPC是Google开源的一种高性能、跨语言的远程过程调用(RPC)框架,它使用ProtocolBuffers作为序列化工具,支持多种编程语言,如C++,Java,Python,Go等。gR...

Etcd服务注册与发现封装实现--golang

服务注册register.gopackageregisterimport("fmt""time"etcd3"github.com/cor...

Golang:将日志以Json格式输出到Kafka

在上一篇文章中我实现了一个支持Debug、Info、Error等多个级别的日志库,并将日志写到了磁盘文件中,代码比较简单,适合练手。有兴趣的可以通过这个链接前往:https://github.com/...

如何从 PHP 过渡到 Golang?(php转golang)

我是PHP开发者,转Go两个月了吧,记录一下使用Golang怎么一步步开发新项目。本着有坑填坑,有错改错的宗旨,从零开始,开始学习。因为我司没有专门的Golang大牛,所以我也只能一步步自己去...