简介

List接口继承自Collection接口,是Collection三大延伸接口之一。List中的元素都是有序的,并且都支持用索引访问。同时List中的元素允许重复。

public interface List<E> extends Collection<E>
方法

List中Collection接口中大部分方法又重新定义了一遍,当然也有定义自己特有的方法,这里重要讲特有方法,其他方法请参考上一篇Collection接口。

// 替换所有 UnaryOperator会另开一篇讲解
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
// 排序
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
// 主要使用 Arrays.sort 进行排序
Arrays.sort(a, (Comparator) c);
// 迭代原集合
ListIterator<E> i = this.listIterator();
// 遍历新数组
for (Object e : a) {
i.next();
// 使原集合中元素位置跟新数组中一致,这里直接替换
i.set((E) e);
}
}
// 根据索引查找
E get(int index);
// 根据索引设置元素
E set(int index, E element);
// 根据索引位置添加
void add(int index, E element);
// 根据索引位置删除
E remove(int index);
// 获取元素在集合中的第一个索引
int indexOf(Object o);
// 获取元素在集合中最后一个索引
int lastIndexOf(Object o);
// 获取一个列表迭代器
ListIterator<E> listIterator();
// 从某个位置开始构建迭代器
ListIterator<E> listIterator(int index);
// 截取某一段构建集合
List<E> subList(int fromIndex, int toIndex);

相对于Collection接口来说,List接口增加了很多索引操作,并且不仅仅提供普通Iterator迭代器,并且提供ListIterator列表迭代器,双向操作更加方便

AbstractList 抽象类

AbstractList实现List接口,从名字就可以看出该类也是抽象类,提供了对列表类操作的一些基本实现。

public abstract class AbstractList<E>
extends AbstractCollection<E> implements List<E>
构造函数
protected AbstractList() {
}
属性
// 修改次数
protected transient int modCount = 0;
未实现的方法
abstract public E get(int index);
已实现的方法

AbstractList中除了极少数方法没有被子类覆盖(如equals、hashCode),大部分方法都被子类覆盖

添加
public boolean add(E e) {
add(size(), e);
return true;
}

public void add(int index, E element) {
throw new UnsupportedOperationException();
}

public boolean addAll(int index, Collection<? extends E> c) {
// 是否越界校验
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}

private void rangeCheckForAdd(int index) {
if (index < 0 || index > size())
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

add(E e)调用add(int index, E element),注意直接调用会抛异常,子类必须覆盖此方法

设值
public E set(int index, E element) {
throw new UnsupportedOperationException();
}

同样需要注意,直接调用会抛异常,子类必须覆盖此方法

删除
public E remove(int index) {
throw new UnsupportedOperationException();
}

protected void removeRange(int fromIndex, int toIndex) {
// 按起始位置构建列表迭代器
ListIterator<E> it = listIterator(fromIndex);
// 遍历范围内的所有元素
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
// 迭代删除
it.next();
it.remove();
}
}

直接调用remove(int index)会抛异常,子类必须覆盖此方法

查找
// 获取元素索引
public int indexOf(Object o) {
// 获取此集合列表迭代器
ListIterator<E> it = listIterator();
if (o==null) {
// 参数为空时找元素为空的索引
while (it.hasNext())
// 找到第一个就返回
if (it.next()==null)
return it.previousIndex();
} else {
// 参数不为空,找元素和参数equals一样的索引
while (it.hasNext())
// 找到第一个就返回
if (o.equals(it.next()))
return it.previousIndex();
}
// 没有找到返回-1
return -1;
}

// 按索引查找
public int lastIndexOf(Object o) {
// 获取此集合列表迭代器
ListIterator<E> it = listIterator(size());
if (o==null) {
// 参数为空时找元素为空的索引,这里是从最后一个找起
while (it.hasPrevious())
// 找到第一个就返回(倒找找第一个,实际上就是最后一个)
if (it.previous()==null)
return it.nextIndex();
} else {
// 参数不为空,找元素和参数equals一样的索引(倒着找)
while (it.hasPrevious())
// 找到第一个就返回(倒找找第一个,实际上就是最后一个)
if (o.equals(it.previous()))
return it.nextIndex();
}
// 没有找到返回-1
return -1;
}
清空
public void clear() {
// 从第一个元素开始删除
removeRange(0, size());
}
hashCode方法
public int hashCode() {
// 初始化为1,如果元素为空,hashCode就为1
int hashCode = 1;
for (E e : this)
// 上一次 hashCode 乘以31,加上当前元素的 hashCode
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
// 返回 hashCode
return hashCode;
}
equals方法
public boolean equals(Object o) {
// 参数与当前集合内存地址一样,返回true
if (o == this)
return true;
// 参数不是List或List子类的实例,返回false
if (!(o instanceof List))
return false;
// 获取两个迭代器
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
// 同时迭代两个集合,同时有值才可以迭代
while (e1.hasNext() && e2.hasNext()) {
// 分别获取元素
E o1 = e1.next();
Object o2 = e2.next();
// 判断两个元素是否一致,都为空或equals一致
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
// 能到这至少有一个迭代完,有一个没迭代完就返回false
return !(e1.hasNext() || e2.hasNext());
}
迭代器
// 获取迭代器
public Iterator<E> iterator() {
return new Itr();
}
// 获取列表迭代器
public ListIterator<E> listIterator() {
return listIterator(0);
}
// 从某一位置构建迭代器
public ListIterator<E> listIterator(final int index) {
rangeCheckForAdd(index);

return new ListItr(index);
}
内部类Itr
private class Itr implements Iterator<E> {

int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount; public boolean hasNext() {...}
public E next() {...}
public void remove() {...}
final void checkForComodification() {...}
}

此内部类主要是实现Iterator迭代器基本功能

内部类ListItr
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {...}
public boolean hasPrevious() {...}
public E previous() {...}
public int nextIndex() {...}
public int previousIndex() {...}
public void set(E e) {...}
public void add(E e) {...}
}

此内部类继承Itr并实现ListIterator,经典的适配器模式,并且扩展Itr,使其拥有双向迭代功能

外部内SubList
class SubList<E> extends AbstractList<E>

SubList类继承自AbstractList抽象类,因此它的实例列表可以使用AbstractList的各种已经实现的方法。

外部类RandomAccessSubList
class RandomAccessSubList<E>
extends SubList<E> implements RandomAccess

RandomAccessSubList类继承自SubList,并实现了RandomAccess接口,RandomAccess接口只是表示此类的实例支持随机访问。

数据结构 - List 接口的更多相关文章

  1. 【C/C++学院】0828-数组与指针/内存分配/数据结构数组接口与封装

    [送给在路上的程序猿] 对于一个开发人员而言,可以胜任系统中随意一个模块的开发是其核心价值的体现. 对于一个架构师而言,掌握各种语言的优势并能够运用到系统中.由此简化系统的开发,是其架构生涯的第一步. ...

  2. 数据结构-List接口-LinkedList类-Set接口-HashSet类-Collection总结

    一.数据结构:4种--<需补充> 1.堆栈结构:     特点:LIFO(后进先出);栈的入口/出口都在顶端位置;压栈就是存元素/弹栈就是取元素;     代表类:Stack;     其 ...

  3. java中常用的数据结构--Collection接口及其子类

    java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类. 一.集合和数组的区别 二.C ...

  4. 数据结构 - Collection接口

    简介 Collection继承自Iterable,Collection接口是Java集合两大分支中的一支,Queue.List.Set都是Collection的扩展:集合大类分为了Collection ...

  5. android系统平台显示驱动开发简要:Samsung LCD接口篇『三』

    平台信息: 内核:linux3.4.39系统:android4.4 平台:S5P4418(cortex a9) 作者:瘋耔(欢迎转载,请注明作者) 欢迎指正错误,共同学习.共同进步!! 关注博主新浪博 ...

  6. 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用

    转自:http://kakajw.iteye.com/blog/935226 一.java对象的比较 等号(==): 对比对象实例的内存地址(也即对象实例的ID),来判断是否是同一对象实例:又可以说是 ...

  7. 【转】Android LCD(三):Samsung LCD接口篇

    关键词:android LCD控制器 Framebuffer PWM  平台信息:内核:linux2.6/linux3.0系统:android/android4.0 平台:samsung exynos ...

  8. JAVA学习笔记 -- 数据结构

    一.数据结构的接口 在Java中全部类的鼻祖是Object类,可是全部有关数据结构处理的鼻祖就是Collection和Iterator接口,也就是集合与遍历. 1.Collection接口 Colle ...

  9. Android LCD(三):Samsung LCD接口篇

    关键词:android LCD控制器 Framebuffer PWM  平台信息: 内核:linux2.6/linux3.0 系统:android/android4.0  平台:samsung exy ...

随机推荐

  1. java中的二维数组基础知识

    二维数组基本知识,毕竟常见的有:概念,初始化,遍历 概念: 理解二维数组,首先要先理解一维数组是什么.一维数组是个容器,存储相同数据类型的容器(这里不再做一位数组的具体介绍).二维数组就是用来存储一维 ...

  2. 应用场景:vue表格撤销删除与保存按钮的显隐

    应用场景:vue表格撤销删除与保存按钮的显隐

  3. win10安装MAYA失败,怎么强力卸载删除注册表并重新安装

    一些搞设计的朋友在win10系统下安装MAYA失败或提示已安装,也有时候想重新安装MAYA的时候会出现本电脑windows系统已安装MAYA,你要是不留意直接安装MAYA,只会安装MAYA的附件或者直 ...

  4. openssl内存分配,查看内存泄露

    openssl内存分配 用户在使用内存时,容易犯的错误就是内存泄露.当用户调用内存分配和释放函数时,查找内存泄露比较麻烦.openssl提供了内置的内存分配/释放函数.如果用户完全调用openssl的 ...

  5. <SCOI2008>奖励关

    emmm第一道期望dp+个状压 真有趣.. #include<cstdio> #include<iostream> #include<cstring> #inclu ...

  6. 深入 Java 调试体系: 第 1 部分,JPDA 体系概览

    JPDA 概述 所有的程序员都会遇到 bug,对于运行态的错误,我们往往需要一些方法来观察和测试运行态中的环境.在 Java 程序中,最简单的,您是否尝试过使用 System.out.println( ...

  7. <JZOJ5910>duliu

    愤怒 考场想到正解 然后觉得我的“正解”和正解差不多 一样的效果 被忽略的与正解的不同也想到了 然而 我懒得再写 于是快乐10分 气坏了 #include<cstdio> #include ...

  8. unittest(20)- 自动更新表格中数据(5)

    # 1. get_data.py from tools import project_path import pandas as pd class GetData: Cookie = None Add ...

  9. unittest(20)- 自动更新表格中的测试数据(1)

    # 直接给出第一个手机号,而不是从excel中取数据 from openpyxl import load_workbook from tools.read_config import ReadConf ...

  10. Laravel wxxcx 微信小程序获取用户信息

    wxxcx 是Laravel5微信小程序登录获取用户信息扩展 部署 12345678 # 安装$ composer require iwanli/wxxcx# 注册服务# 在 /config/app. ...