第十四章 集合(集合框架体系、List)

news2024/12/23 18:08:47

一、集合框架体系

(1)可以动态保存任意多个对象
(2)提供了一系列方便的操作对象的方法:add、remove、set、get等

集合框架体系:

二、Collection

1. Collection 接口常用方法

(1)add:添加单个元素

(2)remove:删除指定元素

(3)contains:查找元素是否存在

(4)size:获取元素个数

(5)isEmpty:判断是否为空

(6)clear:清空

(7)addAll:添加多个元素

(8)containsAIl:查找多个元素是否都存在

(9)removeAll:删除多个元素

2. Collection 接口遍历元素方式1,使用 Iterator(迭代器)

(1)Iterator 对象称为迭代器,主要用于遍历 Collection集合 中的元素
(2)所有实现了 Collection接口 的集合类都有一个 iterator() 方法,用以返口一个实现了Iterator接口 的对象,即可以返回一个迭代器。
(3)Iterator 仅用于遍历集合,lterator 本身并不存放对象

public class Test {

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

        // list.iterator() 重置迭代器,可重复
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            Integer next = iterator.next();
            System.out.println(next);
        }
    }
}

3. Collection 接口遍历元素方式2,for循环增强

增强 for 循环,可以代替 iterator 迭代器,特点:增强 for 本质就是迭代器。只能用于遍历集合或数组。

public class Test {

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

        for (Integer e : list) {
            System.out.println(e);
        }
    }
}

三、List

1. List 接口基本介绍

(1)List 接口是 Collection 接口的子接口

(2)List 集合类中元素有序(即添加顺序和取出顺序一致)、且可重复

(3)List 集合中的每个元素都有其对应的顺序索引,即支持索引。

(4)List 容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素

2. List 集合里添加了一些根据索引来操作集合元素的方法

(1)void add (int index, Object ele):在 index 位置插入 ele 元素

(2)boolean addAll (int index, Collection eles):从 index 位置开始将 eles 中的所有元素添加进来

(3)Object get (int index):获取指定 index 位置的元素

(4)int indexOf (Object obj):返回 obj 在集合中首次出现的位置

(5)int lastlndexOf (Object obj):返回 obj 在当前集合中末次出现的位置

(6)Object remove (int index):移除指定 index 位置的元素,并返回此元素

(7)Object set (int index, Object ele):设置指定 index 位置的元素为 ele,相当于是替换

(8)List subList (int fromlndex,int tolndex):返回从 fromlndex 到(tolndex -1)位置的子集合

public class Test {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("乔峰");
        list.add("段誉");
        list.add(1, "虚竹");
        list.add("Tom");
        System.out.println(list); // [乔峰, 虚竹, 段誉, Tom]

        List<String> list2 = new ArrayList<>();
        list2.add("Jack");
        list2.add("Tom");
        list.addAll(1, list2);
        System.out.println(list); // [乔峰, Jack, Tom, 虚竹, 段誉, Tom]

        System.out.println(list.get(1)); // Jack
        System.out.println(list.indexOf("Tom")); // 2
        System.out.println(list.lastIndexOf("Tom")); // 5

        list.remove(5);
        System.out.println(list); // [乔峰, Jack, Tom, 虚竹, 段誉]
        list.set(2, "Mike");
        System.out.println(list); // [乔峰, Jack, Mike, 虚竹, 段誉]
        System.out.println(list.subList(0, 2)); // [乔峰, Jack]
    }
}

四、ArrayList(P509)

1. ArrayList的注意事项

(1)ArrayList 可以加入 null,并且多个

(2)ArrayList 是由数组来实现数据存储的

(3)ArrayList 基本等同于 Vector。ArrayList 是线程不安全(执行效率高),在多线程情况下,不建议使用ArrayList

2. ArrayList的底层操作机制源码分析(P510)

(1)ArrayList 中维护了一个 Object 类型的数组,transient Object[] elementData【transient  表示该属性不会被序列化】

(2)当创建 ArrayList  对象时,如果使用的是无参构造器,则初始 elementData 容量为 0。

第一次添加,则扩容 elementData 为 10。如果需要再次扩容的话,则扩容 elementData 为1.5 倍

(3)如果使用的是指定大小的构造器,则初始 elementData 容量为指定大小,如果需要扩容,则直接扩容 elementData 为1.5倍。

public class ArrayList_<E> {

    transient Object[] elementData;

    private int size;

    protected transient int modCount = 0;

    private static final int DEFAULT_CAPACITY = 10;

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    // 无参构造
    public ArrayList_() {
        // 创建一个空的数组
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    public ArrayList_(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } 
    }

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 在 elementData[size] 赋值,并且size++
        elementData[size++] = e;
        return true;
    }

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private void ensureExplicitCapacity(int minCapacity) {
        // 操作次数
        modCount++;

        // overflow-conscious code
        // 判断是否扩容,如果elementData数组大小不够就扩容
        if (minCapacity - elementData.length > 0){
            grow(minCapacity);
        }

    }

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    // 扩容方法
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // 扩容为1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0){
            newCapacity = minCapacity;
        }
        // 防止超过最大值2147483639
        if (newCapacity - MAX_ARRAY_SIZE > 0){
            newCapacity = hugeCapacity(minCapacity);
        }
        // minCapacity is usually close to size, so this is a win:
        // Arrays.copyOf 可以保留原先的数据,并扩容
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0){
            // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
    }
}

五、Vector(P513)

1. Vector 的基本介绍

(1)Vector 类的定义说明

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

(2)Vector 底层也是一个对象数组 protected Object[] elementData;

(3)Vector 是线程同步的,即线程安全,Vector 类的操作方法带有 synchronized

(4)在开发中,需要线程同步安全时,考虑使用 Vector

 2. Vector 的底层操作机制源码分析

Vector 扩容源码类似于 ArrayList

public class Vector_<E> {

    protected Object[] elementData;

    protected int capacityIncrement;

    protected transient int modCount = 0;

    protected int elementCount;

    public Vector_() {
        this(10);
    }

    public Vector_(int initialCapacity) {
        this(initialCapacity, 0);
    }

    public Vector_(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0){
            throw new IllegalArgumentException("Illegal Capacity: "+
                    initialCapacity);
        }
        // 初始化数组
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        // 判断是否扩容
        if (minCapacity - elementData.length > 0){
            grow(minCapacity);
        }
    }

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // newCapacity = oldCapacity + oldCapacity
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0){
            newCapacity = minCapacity;
        }
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
}

六、LinkedList(P515)

1. LinkedList 说明

(1)LinkedList 底层实现了双向链表双端队列特点
(2)可以添加任意元素(元素可以重复),包括 null
(3)线程不安全,没有实现同步

2. LinkedList 的底层操作机制

(1)LinkedList 底层维护了一个双向链表
(2)LinkedList 中维护了两个属性 first 和 last 分别指向首节点和尾节点
(3)每个节点(Node对象),里面又维护了 prev 、next 、item 三个属性,其中通过 prev 指向前一个,通过 next 指向后一个节点。最终实现双向链表

(4)所以 LinkedList 的元素的添加和删除,不是通过数组完成的,相对来说效率较高

3. LinkedList 源码解读(P516)

public class LinkedList_<E> {

    transient int size = 0;
    protected transient int modCount = 0;

    transient Node<E> first;

    transient Node<E> last;

    private static class Node<E> {
        E item; // 存放数据
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

    public boolean add(E e) {
        linkLast(e);
        return true;
    }

    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null) {
            first = newNode;
        } else {
            l.next = newNode;
        }
        size++;
        modCount++;
    }

    public E remove() {
        return removeFirst();
    }

    public E removeFirst() {
        final Node<E> f = first;
        if (f == null) {
            throw new NoSuchElementException();
        }
        return unlinkFirst(f);
    }

    private E unlinkFirst(Node<E> f) {
        // assert f == first && f != null;
        final E element = f.item;
        final Node<E> next = f.next;
        f.item = null;
        f.next = null; // help GC
        first = next;
        if (next == null) {
            last = null;
        } else {
            next.prev = null;
        }
        size--;
        modCount++;
        return element;
    }
}

七、ArrayList和LinkedList比较(P517)

(1)如果我们改查的操作多,选择 ArrayList
(2)如果我们增删的操作多,选择 LinkedList
(3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择 ArrayList

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

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

相关文章

学习QCustomPlot【3】库结构

文章目录一、前言二、库结构三、图层3.1、坐标轴层一、前言 学习一个陌生的库&#xff0c;我们首先要明确它有什么用&#xff0c;可以结合库官方examples&#xff0c;学习怎么简单的用。 但是如果要对该库有一个全面的认识&#xff0c;还是需要了解它的开发思路和库结构。 例…

2、计算机视觉之图像分类算法基础(笔记)

什么是图像分类&#xff1f; 识别图像所表示内容的任务称为图像分类。我们可以对图像分类模型进行训练以识别各类图像。例如&#xff0c;您可以训练模型来识别表示三种不同类型动物的照片&#xff1a;兔子、仓鼠和狗。 下面几个神经网络重点关注准确率的问题 上图只是训练方式…

java—for结构

for循环语句1.1循环结构循环结构的组成&#xff1a;初始化语句条件判断语句循环体语句条件控制语句循环结构对应的语法&#xff1a;初始化语句条件判断语句循环体语句条件控制语句1.2for循环语句格式//格式 for (初始化语句;条件判断语句;条件控制语句){ 循环体语句; }执行流程…

记录每日LeetCode 环形链表II Java实现

题目描述&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xf…

06_PyTorch 模型训练[学习率与优化器基类]

当数据、模型和损失函数确定&#xff0c;任务的数学模型就已经确定&#xff0c;接着就要选择一个合适 的优化器(Optimizer)对该模型进行优化。 PyTorch 中所有的优化器(如&#xff1a;optim.Adadelta、optim.SGD、optim.RMSprop 等)均是 Optimizer 的子类&#xff0c;Optimizer…

STM32串口收发、串口中断、串口波特率的理解、普通IO模拟串口

STM32串口收发、串口中断一 、串口中断二、使用DMA三、串口波特率的理解开发环境&#xff1a;stm32cubuMax Keil5一 、串口中断 1.当收到消息的时候&#xff0c;立即进入控制程序,实现通过串口控制硬件&#xff1b; 2.在stm32cubeMax中配置串口 配置全局中断 2.在main函数中…

Django项目搭建_修改目录结构

1.安装环境 使用conda下载Django项目需要的依赖 pip install django2.2.6 -i https://pypi.douban.com/simple/pip install djangorestframework -i https://pypi.douban.com/simple/pip install PymySQL -i https://pypi.douban.com/simple/pip install Pillow -i https://p…

CSDN为什么会发展社区?看看官方怎么说

文章目录&#x1f31f; 课前小差&#x1f31f; 23年可兼收名利&#xff1f;&#x1f31f; 博客之星&#x1f31f; 红包活动&#x1f31f; 相聚线下&#x1f31f; 妙笔生花&#x1f31f; 原力计划&#x1f31f; 个人定位&#x1f31f; 为什么要发展社区&#xff1f;&#x1f31f…

100种思维模型之决策树思维模型-004

选择决定了现状和未来&#xff0c;在生活中有很多选择的机会&#xff0c;但是真的选择对了吗&#xff1f;在该读书的年纪&#xff0c;却想着长大真好。在该工作奋斗的年纪&#xff0c;却后悔自己年轻时没好好读书&#xff0c;而悔恨。其实不是我们没有选择的权利&#xff0c;而…

2023年情人节浪漫表白神器(附源码下载)

2023年情人节将要来临&#xff0c;作为一名程序猿也不要落后了&#xff0c;快来用代码展示你的爱吧&#xff01;下面给大家准备了6款情人节表白神器&#xff0c;把说不出口的话&#xff0c;放到代码里送给你爱的人吧&#xff01;祝大家表白成功&#xff0c;俘获美人心&#xff…

Spring Boot集成 Swagger2 展现在线接口文档

一&#xff1a;swagger是什么&#xff1f; Swagger是一款RESTFUL接口的文档在线自动生成功能测试功能软件。Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。目标是使客户端和文件系统作为服务器以同样的速度来更新文件的方法,参数和模型紧…

浅析云边端协同框架下的“AI+”视频融合能力以及场景应用

随着边缘侧与终端侧业务的规模化落地部署&#xff0c;很多新的业务场景已经逐渐不满足于中心化的云端计算模式。尤其是在AI人工智能技术进一步落地应用的趋势下&#xff0c;基于云边端深度融合与协同的“AI”模式&#xff0c;在满足用户对视频服务的智能识别需求上&#xff0c;…

centos环境docker安装nexus3搭建maven私有仓库

拉取最新nexus3镜像docker pull nexus3创建宿主机上的映射文件目录&#xff0c;并授权[root1-0002 ~]# mkdir -p /mnt/lckj/nexus/data [root1-0002 ~]# chmod -R 777 /mnt/lckj/nexus/data运行redis&#xff0c;生成相应容器-d 后台启动[root1-0002 ~]# docker run -d --name …

Go并发读取string的Panic问题

上问题&#xff0c;先看下panic的函数栈信息&#xff0c;说现实strings.Count()发生了panic&#xff0c;来看下函数 第一个参数是字符串s&#xff0c;再结合函数栈信息的十六进制&#xff0c;0x0、0x9表示字符串s的地址和长度 这里来看一下string的底层数据结构&#xff1a;…

Spring Security OAuth2.0认证授权

目录 1.基本概念 1.1什么是认证 1.2什么是会话&#xff1f; 1.2什么是授权 1.3授权的数据模型 1.4.1基于角色的访问控制 1.4.2基于资源的访问控制 2.基于Session的认证方式 2.1认证流程 分布式系统认证方案 什么事分布式系统&#xff1f; 分布式认证需求 分布式认证…

行业安全解决方案 | 能源行业如何在新时期建设新安全?

伴随5G、人工智能、大数据、云计算等新技术的蓬勃发展&#xff0c;数智化成为传统电力能源转型发展的重要方向。与此同时&#xff0c;伴随着能源行业数字技术与电力技术、业务生产的愈发深度的融合&#xff0c;新时期的能源行业网络安全形势有了新变化&#xff0c;网络边界威胁…

DPDK实现的用户态协议栈(UDP)

DPDK实现的用户态协议栈背景NIC与DPDK的比较环境配置Windowe下配置静态IP表代码实现总结背景 DPDK接管NIC之后&#xff0c;接收到的数据都是原始数据&#xff0c;要实现一个协议栈就必须解析协议包和打包协议包&#xff0c;DPDK提供了丰富的API可以使用。 以UDP协议为例&#…

redis分布式集群

文章目录一、redis持久化1.1.RDB持久化1.1.1.执行时机1.1.2.RDB原理1.1.3.小结1.2.AOF持久化1.2.1.AOF原理1.2.2.AOF配置1.2.3.AOF文件重写1.2.4.小结1.3.RDB与AOF对比二、Redis主从集群2.1.集群结构2.2.准备实例和配置2.3.启动2.4.开启主从关系2.5.测试2.6.主从数据同步原理2.…

MMLAB学习笔记-DAY1

一、机器学习 1.机器学习的典型范式 监督学习&#xff1a;数据是由人工标注的&#xff0c;数据之间存在某种映射关系&#xff0c;目的是让机器学习到数据和标签之间的关系无监督学习&#xff1a;数据是没有标签的&#xff0c;通过对数据分析&#xff0c;运用聚类等方法探索出…

六、循环语句

一、while循环 1.语法 while 条件:条件成⽴重复执⾏的代码1条件成⽴重复执⾏的代码2.....2.应用 #偶数累加 i 1 resualt 0while i<100:if i % 2 0:resualt ii1print(resualt)3.break和continue 说明&#xff1a; 举例&#xff1a;⼀共吃5个苹果&#xff0c;吃完第⼀个&…