Java进阶之集合框架(List)

实战指南:彻底清除TIA Portal卸载后遗留的SQL Server WinCC实例 本文详细介绍了如何彻底清除TIA Portal卸载后遗留的SQL Server WinCC实例,解决重新安装时的冲突问题。通过控制面板排查、注册表验证、安全卸载操作流程和注册表深度清理等步骤,确保完全移除残留组件,避免系统崩溃。文章还提供了安装环境重建策略和预防措施,帮助工程师高效管理西门子自动化软件。 阅读详情

基本内容】

     集合框架是Java编程开发中最常用的技术框架。Java的集合框架主要分为单列集合和双列集合,本章主要讲述单列集合。

    单列集合的根接口是Collection接口,下分三个子接口:List、Set、Queue, 三个子接口的特征如下图表:

图片

     其中的有序无序不是指元素值的大小顺序,而是指元素存取的顺序一致,即以什么顺序存入的,取出时就是什么顺序,例如以下ArrayList代码:

    ArrayList是按索引的顺序存入1、4、2、3,因而按索引顺序打印出来的也是1、4、2、3。 

    关于单列集合主要的继承关系如下图:

图片

     这图主要列出了三个分类接口的主线继承关系,但为了满足开发人员的各种需求,实际上Jdk提供的集合类各种数据结构繁多,继承关系远比上图复杂,还有许多分支。我们先从List接口开始一一介绍。

     一、List接口

     List接口主要有以下几个实现类:ArrayList、LinkedList、Vector和Statck,其中LinkedList继承关系稍复杂,后面单列。下图为List实现类的区别:

图片

     其中,ArrayList、Vector和Statck因为存储结构采用的都是数组,即顺序存储,因而元素存取的时间复杂度同顺序表: 查询时间复杂度为O(1),插入和删除时间复杂度为O(n),而LinkedList底层存储是双向链表即链式存储,因而其时间复杂度刚好相反: 查询时间复杂度为O(n),插入和删除时间复杂度为O(1)。关于存储结构和顺序表相关概念可参看作者相关文章数据结构和算法之基本概念数据结构和算法之线性结构

     ArrayList和Vector

     ArrayList虽然底层是用数组实现,但是在设计目标上,又不完全等同于数组,数组是纯粹的顺序表,存储空间是预先分配的不能动态扩容,而ArrayList允许动态扩容,那ArrayList是怎么实现的呢?我们先看看ArrayList的部分定义代码:


public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    @java.io.Serial
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

       第二段申明其构造函数的代码:      

/**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        Object[] a = c.toArray();
        if ((size = a.length) != 0) {
            if (c.getClass() == ArrayList.class) {
                elementData = a;
            } else {
                elementData = Arrays.copyOf(a, size, Object[].class);
            }
        } else {
            // replace with empty array.
            elementData = EMPTY_ELEMENTDATA;
        }
    }

      从上述两段代码可以看出,ArrayList底层是用数组来存储元素的,其中成员变量elementData是用来动态增删元素的,而其私有成员变量DEFAULTCAPACITY_EMPTY_ELEMENTDATA 则是用来初始化的缺省空数组,而数组缺省大小为DEFAULT_CAPACITY的值10。

      继续看ArrayList的代码: 


private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

    private Object[] grow() {
        return grow(size + 1);
    }
    
    ......
    
    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }
    
    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

     从上述代码可以看出,当往ArrayList增加数据元素时,会校验数组的大小是否已经等于元素的个数,如果相等就会调用grow()方法进行动态扩容。而grow()方法则会调用数组辅助类Arrays.copyof()方法按指定长度创建新的数组,并把原数组拷贝拷贝过去,从而实现动态扩容。有关数组及辅助类知识请参看作者相关文章Java基础之数组

     以上是ArrayList动态扩容的代码,而Vector同样是用动态数组实现的,它的动态机制和ArrayList大同小异,这里就不再深究代码,不同的是Vector的方法基本上是用同步修饰符synchronized修饰,从而保证了线程安全,而Stack直接继承了Vector,因而也是线程安全的,只不过追加了先进后出的逻辑。

      在Java后续的新版本中,因为性能问题,都不再推荐使用Vector和Stack,那如果只用ArrayList,怎么保证特定场景下的线程安全需求呢?这个方法有很多种:方法一,可参考Vector代码,使用synchronized关键字来保证;方法二,可以使用集合辅助类Collections.synchronizedList() 方法来得到一个线程安全的集合,例如:

List<E> myArrayList = Collections.synchronizedList(new ArrayList<E>());

      方法三可以使用 CopyOnWriteArrayList 类替代ArrayList,该类是 Java 并发包(java.util.concurrent)中提供的一个线程安全的列表实现。它在读取操作上没有锁,并且支持在迭代期间进行修改操作,而不会抛出 ConcurrentModificationException 异常。示例如下:

CopyOnWriteArrayList<E> myArrayList = new CopyOnWriteArrayList<E>();

     最后的一个方法,您还可以使用显式锁(如 ReentrantLock)来手动实现对 ArrayList 的同步, 它是java.util.concurrent.locks 包中提供的, 相关代码可以自己去尝试实现。

      LinkedList

      LinkedList虽然也实现了List接口,但它不是List接口的纯正血脉,它还间接实现了Queue接口,它的继承关系较为复杂;此外,它的底层结构是按双向链表结构实现的,因而特性和前面三个相反,在插入和删除操作上更高效,但在随机访问时效率较低,因为查询需要遍历链表‌;因而在List接口家族中,LinkedList算是另类。我们先看它的完整继承关系,如下图;

图片

    从上图的继承关系可以看出,LinkedList如前文所说,既实现了List接口,同时也实现了Queue接口的子接口双端队列接口Deque,因而LinkedList可用于双端队列的实现。那怎么确定LinkedList底层是双向链表结构呢?我们可以查看它的源代码定义,如下:



public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    transient int size = 0;

    /**
     * Pointer to first node.
     */
    transient Node<E> first;

    /**
     * Pointer to last node.
     */
    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;
        }
    }

   ......
}
 

     从上述代码可以看出,LinkedList底层是双向链表结构,每个元素都是一个嵌套类Node结点,里面包括本身元素的值和指向前后元素的指针。LinkedList和ArrayList一样是线程非安全的,它的方法上没有使用synchronized修饰,要保证它的线程安全,可以参考前述内容ArrayList使用的方式。

     List接口及其实现类的介绍就到这里,总之,我们需要深刻理解其各实现类的异同,其各自的特性,正是它们底层结构和实现方式的外在体现。

【注意事项

1.LinkedList的归属:在有的文章中,会把LinkedList归属到Queue接口下讲解,这个无可厚非。只是作者认为Queue的显著特性是先进先出,而LinkedList虽然能用来实现队列的这一特性,但先进先出并不是LinkedList本身具有的特性,因而还是把它归类为List接口下讲解。

2.接口特性规范的说明:在文章中列出的三个接口List、Set和Queue的特征,例如元素是否可为空,元素是否有序,这些在接口的实现类中,并不会严格遵循,只能作为接口设计的初衷和一般规范;另外像LinkedList这样既实现了List接口,又实现了Queue接口,可能无法同时满足两者的规范特性。

码农爱刷题

为计算机编程爱好者和从业人士提供技术总结和分享 !为前行者蓄力,为后来者探路!

10篇原创内容

公众号

              如有错误或不足,欢迎指正!

manimgl安装 安装manimgl 阅读详情

相关推荐

ksz9031 mmd读取不了_ZYNQ. LwIP.PHY.KSZ9031RNX

新一块板子米尔科技的z-turn 使用的PHY芯片是Micrel的 KSZ9031RNX 而不是zedboard上的Marvell的。直接使用lwip的echo server demo时会报错 , 无法启动。在网上找了很久终于找到几篇关于这个问题的文章。修改PHY的驱动xemacpsif_physpeed.c文件该芯片的PHY Identifier 是 0x0022bsp设置中修改参数以提速MEM...

weixin_39626298的博客 903

Java数据结构————List

集合框架中,List是一个接口,继承自Collection,并不能直接用来实例化。站在数据结构的角度来看,List就是一个线性表,即n个具有相同类型元素的有限序列,在该序列上可以执行增删改查以及变量等操作。Collection也是一个接口,该接口中规范了后序容器中常用的一些方法,具体如下所示:Iterable也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,

qq_45559559的博客 3914

uni-app - 文本展开 / 收起折叠功能,支持自定义样式(当文本内容超出规定行数后,展开收起折叠的功能)兼容 H5 / App / 小程序且易用更容易修改的插件组件源码,超详细的示例代码及注释

uniapp实现文本的展开与收起功能,uniapp展开全部和收起,uniapp里文本的展开与收起,uniapp中文本内容超出规定行数后展开收起的处理,UNIAPP兼容h5、微信小程序多行文本展开或收起,uni-app中,文字超出隐藏并显示省略号(实现展开、收起全文),uni-app中文本过长-实现折叠与展开效果,中文本内容超出规定行数(字数)后展开收起的处理,超出部分...显示,uniapp适用于uniapp多行文本溢出显示...,多行文本展开或收起,uni-app-文本展开/收起折叠功能,支

🏆 前端领域优质创作者 5598

JAVA ---List

java -- List

jc15274630894的博客 812

Java数据结构(List介绍和顺序表)

顺序表常用的简单接口的实现

qq_40599849的博客 1470

Java集合框架List系列集合(从0到1详解,并附有代码+案例)

不能直接存储基本数据类型,如果要存储基本数据类型,需要将基本数据类型变成对应的包装类再存储在集合里面。同List系列中的方法(即 List中的方法都可以用),加上LinkedList独有的方法…底层数据结构是双链表,查询慢,增删块,但是如果操作的是首尾元素,速度极快。LinkedList本身多了很多直接操作首尾元素的特有的API。List集合因为有索引,多以多了很多索引操作的方法。(Collection中的方法List都可以用)集合可根据存储的内容的长度。List集合中的特有方法。

Java技术加油站的博客 1662

Java集合(List,LinkedList,Set,HashSet,TreeSet,Vector,Map,Collections)

本文主要介绍了Java集合的概念,介绍了Java中常用的集合集合的API,具体介绍了:Collection集合,List集合,ArrayList集合,集合的遍历,LinkedList集合,Set集合,HashSet集合,TreeSet集合,Vector集合,Map集合,Collections集合工具类,并附有模拟斗地主洗牌案例,输出字符串输入次数案例,有助于大家学习Java中的集合

fj123321666的博客 521

Java进阶核心之集合框架List

Java进阶核心之集合框架List 什么是List数据结构 List接⼝是⼀个有序的 Collection,线性列表接⼝,能够精确的控制每个元素插⼊的位置,能够通过索引(类似于数组的下标)来访问List中的元素,第⼀个元素的索引为 0,⽽且允许有相同的元素,接⼝存储⼀组不唯⼀,有序(插⼊顺序)的对象。 常见的实现类 ArrayList 基于数组实现,是⼀个动态的数组队列,但它和Java中的数组⼜不⼀样,它的容量可以⾃动增⻓ 可以存储任意多的对象,但是只能存储对象,不能存储原⽣数据类型例如int

ruan_luqingnian的博客 554

获取list集合中某一元素的值_Java 进阶集合框架2

目录一、List 接口1. 概述2. List 接口中的抽象方法(特有)3. List 遍历二、ListIterator 接口1.概述2. ListIterator 接口的抽象方法3. List 逆向遍历:三、迭代器的并发修改异常1. 迭代器的并发修改异常2. 出现场景:3. 原因:四、ArrayList 、LinkedList 集合1. ArrayList 集合2. LinkedList 集合3...

weixin_39748183的博客 2547

list集合下标从几开始_Java基础进阶 集合框架详解

今日任务1、List接口介绍(掌握常用List特有方法) 2、练习 3、ArrayList介绍(必须清楚集合的特征、掌握集合中的方法) 4、LinkedList介绍(必须清楚集合的特征、掌握集合中的方法) 5、Vector 类介绍(了解) 6、List下的子类总结(掌握) 7、Set 接口介绍(掌握Set集合的特性) 8、HashSet 集合(掌握HashSet集合的应用)1、List接口介绍在学...

weixin_39931146的博客 6551

java list 底层构建_Java基础进阶 集合框架详解

今日任务1、List接口介绍(掌握常用List特有方法)2、练习3、ArrayList介绍(必须清楚集合的特征、掌握集合中的方法)4、LinkedList介绍(必须清楚集合的特征、掌握集合中的方法)5、Vector 类介绍(了解)6、List下的子类总结(掌握)7、Set 接口介绍(掌握Set集合的特性)8、HashSet 集合(掌握HashSet集合的应用)1、List接口介绍在学习Collec...

weixin_33900596的博客 376

Java 集合框架进阶——List 实现类深度解析与实战优化

摘要: Java集合框架中,List是最常用的有序集合接口。本文深度解析四大实现类: ArrayList:动态数组结构,随机访问O(1),扩容1.5倍,非线程安全,适合绝大多数场景; LinkedList:双向链表,头尾操作O(1),内存占用高,适合频繁增删场景; Vector:线程安全但性能差,已过时; CopyOnWriteArrayList:写时复制,读多写少并发场景首选。 优化建议:预分配容量、避免subList陷阱、选择高效遍历方式、批量操作优先。开发中95%场景推荐ArrayList,并发读多写

m0_57545130的博客 272

JAVA 集合框架进阶List 与 Set 的深度解析与实战

摘要: 本文深度解析Java集合框架中的List与Set核心差异,从底层实现、性能特征到使用场景进行对比。List有序允许重复,支持索引访问;Set无序不可重复,依赖equals/hashCode去重。重点对比ArrayList、LinkedList、HashSet、TreeSet等实现类的性能指标(如ArrayList随机访问O(1),LinkedList插入O(1)),并给出线程安全方案(如CopyOnWriteArrayList)。针对业务场景提供代码模板,如LinkedHashSet保序去重、Tre

likuoelie的博客 362

Java 进阶】万字详解集合框架:从原理到源码,彻底搞懂 List、Set、Map

Java集合框架深度解析:从原理到实战 本文全面剖析Java集合框架核心组件,涵盖List、Set、Map三大体系。详细讲解ArrayList的动态扩容机制、LinkedList的双向链表结构、HashMap的JDK1.8红黑树优化等关键技术点。特别对比了不同版本实现差异,如JDK1.7和1.8的HashMap结构变化,以及ConcurrentHashMap的分段锁演进为CAS+synchronized的优化过程。

m0_58782205的博客 1113

java集合的结构list类型

collection 集合 Course.java代码如下所示: /** * 课程类 */ public class Course { public String id; public String name; public Course(String id,String name){ this.id = id; this.name = name; } //添加一个无参构造器 public Course() { ...

gb4215287的博客 1957

Java中的List: 理解与实践

Java编程语言中,List是一种被广泛使用的集合类型,它提供了一种灵活的方式来存储和操作有序的元素序列。ListJava集合框架Java Collections Framework)的一部分,是一个接口,提供了一系列标准的方法来对元素进行增加、删除、检索和遍历操作。

人生嘛!无非是左脚比右脚前,右脚再比左脚前,明天比今天好! 1920

Java——列表(List

ListJava 集合框架中的一种接口,继承自 Collection 接口。添加元素:add(E e)、add(int index, E element)删除元素:remove(Object o)、remove(int index)获取元素:get(int index)修改元素:set(int index, E element)查找元素:indexOf(Object o)、lastIndexOf(Object o)获取列表大小:size()

tm1560000的博客 3181

Json,List,Map的数据格式详解。

JSON的规则很简单:对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’对”之间使用“,”(逗号)分隔。 规则如下: 1、映射用冒号(“:)表示。名称:值 2、并列的数据之间用逗号(“,”)分隔。名称1:值1,名称2:值2 3、映射的集合(对象)用大括号(“{}”)表示。此格式

hoonr的专栏 4万+

Java集合List(超详细)

for-each循环:简洁易读,最适合日常使用。Iterator:提供了更多的控制权,比如在遍历时移除元素,但在大多数情况下不如for-each方便。Stream API:功能强大,支持复杂的集合处理和并行处理,适合进行复杂的聚合操作和过滤操作。

epitomizelu的专栏 1万+

java将字符串转换为list格式

将字符串转换为List格式的方法介绍 在Java中,有时候我们需要将一个字符串转换为List格式,以便于对字符串进行更灵活的操作。本文将介绍几种常见的方法来实现这一功能,并提供相应的代码示例。 方法一:使用split方法 可以使用String类的split方法来将字符串分割为一个字符串数组,然后将该数组转换为List格式。...

weixin_36852275的博客 7131

2021美赛E题思路

2021年美赛E题思路,免积分给大家分享,有需要的同学可以自取

JESD78F 2022 IC LATCH-UP TEST.pdf

JESD78F 2022 IC LATCH-UP TEST.pdf

上一篇: 数据结构和算法之线性结构
下一篇: Java进阶之集合框架(Set)
Liusp
博客等级 码龄25年 251粉丝 32原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值