百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

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

toyiye 2024-06-21 12:05 10 浏览 0 评论

写在前面:

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

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

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

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 是它的替代品

张小飞:原来如此

相关推荐

熬夜会造成神经衰弱,别再熬夜了(熬夜会加重神经衰弱吗)

长时间熬夜会出现神经衰弱,皮肤受损,超重肥胖,记忆力下降等现象……熬夜了能补回来吗?每天少睡一两个小时算熬夜吗?必须上夜班怎么办?如何减少熬夜伤害?戳图转给爱熬夜的TA!via央视新闻来源:河北省文...

落叶知秋的图片爬取(落叶知秋的图片有哪些?)

importrequestsfrombs4importBeautifulSoupimporttimeimportjsonpathimportjsonfromurllib.parsei...

小心有毒!长沙海关查获藏匿在“巧克力威化涂层”中的大麻

来源:海关发布近日,长沙黄花机场海关对一票申报为“巧克力威化涂层”的进境快件进行机检查验时,在包裹内查获封装于各独立威化饼干包装袋中的大麻230克。另从其他申报为“巧克力、儿童早餐谷物”的快件中查获藏...

钧正平:编造传播这种谣言,荒谬(钧正公司)

来源:钧正平工作室官方微博【钧评编造传播这种谣言,荒谬!】目前,乌克兰安全形势还在迅速变化之中,各方面安全风险上升。相关事件网上热度极高,倍受瞩目。然而,有一些人却借机大肆制造散播一些低级谣言,比如...

幸运角色过去了,谈一谈DNF起源的元素

总的来说伤害比上个版本强太多了,打卢克每日和团本明显能感觉的到。目前打团B套+圣耀稍微打造下应该都能随便二拖了。组队基本上都是秒秒秒(以前得强力辅助,现在随便带个毒奶都行)。单刷除了王座和顶能源阿斯兰...

DNF元素超大凉打桩测试(把括号的伤害加起来好像比较正常)

最近修练场的二觉老是很奇怪,发现以前都是习惯性先减抗然后丢二觉,结果伤害。。。直接丢二觉就正常了下面是其他技能伤害,没达到BUG线,估计问题不大。装备打造方面:全身红字加起来353(41*5+74*2...

ANSYS接触和出图技巧(ansys rough接触)

1.ANSYS后处理时如何按灰度输出云图?1)你可以到utilitymenu-plotctrls-style-colors-windowcolors试试2)直接utilitymenu-plotctr...

ANSYS有限元使用经验总结-后处理(4)

28.求塑性极限荷载时,结构的变形应该较大,建议把大变形打开。...

CFopen21.1、CFopen21.2都来了(cfile open)

[呲牙][赞][加油]

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

取消回复欢迎 发表评论:

请填写验证码