java中list是什么:有序集合接口
java中list是什么,它是Java集合框架下的有序、可重复的单列集合接口,位于java.util包,支持按索引存取元素,提供增删改查、遍历、截取子集合方法,常用实现类有ArrayList、LinkedList、Vector,你做普通循环遍历、随机读取优先选ArrayList,频繁头尾增删优先选LinkedList,多线程共享读写场景才考虑Vector,该体系不适合需要键值映射、元素自动去重的业务,这类场景要改用Map或Set。
list接口核心特性
list继承自Collection接口,它规定集合内元素保留存入顺序,同一个对象可以多次存入集合,每个元素绑定一个从0开始的数字索引。你可以直接通过索引定位元素,调用get、set方法完成读取和替换,这一点和Set接口存在明显区别,Set不支持索引访问,并且不允许重复元素。list接口定义了一批专属方法,add(intindex,Eelement)用于在指定位置插入元素,remove(intindex)按索引删除元素,subList(intfromIndex,inttoIndex)截取一段视图,这个视图不是新集合,会和原list共享底层数据。
subList返回的是视图,不是独立新对象。
list常用实现类对比
| 实现类 | 底层结构 | 读取性能 | 中间插入删除性能 |
|---|---|---|---|
| ArrayList | 动态数组 | 较好 | 较差 |
| LinkedList | 双向链表 | 较差 | 较好 |
| Vector | 动态数组,方法加同步锁 | 一般 | 较差 |
ArrayList是开发里使用频次更高的实现类,底层数组容量不足时会触发扩容,默认扩容系数1.5倍,扩容过程需要复制数组,大批量频繁新增元素会产生额外开销。LinkedList除了实现list接口,还实现了Deque接口,你可以把它当成队列、双端队列使用,但它没有数组的随机访问优势,用for循环配合get遍历LinkedList时,每次get都会从头或尾节点遍历查找,整体遍历速度会明显变慢。Vector所有核心方法带有synchronized同步修饰,并发读写时线程安全,同步锁会带来额外性能损耗,非并发场景一般不推荐选用。
list基础代码使用示例
你声明list变量时,推荐使用多态写法,也就是List
迭代器遍历的时候,不能直接调用list的add、remove方法修改集合,会触发并发修改异常ConcurrentModificationException,想要遍历过程删除元素,需要调用迭代器自带的remove方法。这个错误在新手代码里很常见,直接在for循环内执行list.remove,集合修改标记和迭代器预期标记不一致,程序抛出异常中断执行。
list的适用边界
list所有实现类默认都不是线程安全的,多个线程同时写同一个list实例,可能出现元素丢失、数组越界、数据错乱,并发场景可以用Collections.synchronizedList包装,或者选用JUC包下的CopyOnWriteArrayList。CopyOnWriteArrayList写入时复制底层数组,读操作不加锁,适合读多写少的场景,写入操作开销偏大,不适合高频写入的业务。
list可以存放null元素,一个list里面允许存入多个null,索引同样正常分配。
list没有内置排序逻辑,想要排序需要调用Collections.sort,或者list自身的sort方法,传入比较器Comparator自定义排序规则。排序不会改变list有序的基础特性,只是按照指定规则重新调整元素索引位置,和list本身“存入有序”的定义互不冲突。
list的toArray方法存在两个重载版本,不带参数返回Object数组,带数组参数的重载可以返回指定泛型数组,转换时要注意数组长度匹配,长度不足会新建数组,长度富余位置填充null,避免类型转换报错。
list的equals方法判断规则是,两个list所有元素顺序一致、每一个对应位置元素equals相等,就判定为相等,和底层是ArrayList还是LinkedList无关,只看元素序列。
该接口在JDK1.2版本就已经加入集合框架,后续JDK版本持续补充默认方法,比如sort、replaceAll、removeIf,这些默认方法写在接口内,所有实现类都可以直接调用,不需要各自重复实现。
java.util.List和java.awt.List不是同一个类,awt包下的是GUI组件,开发集合业务时不要导错包。
