简介

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. make的工作方式

    摘自<跟我一起写Makefile> GUN的make工作时的执行步骤如下: 1)读入所有的Makefile. 2)读入被include的其他Makeifle. 3)初始化文件中的变量. 4 ...

  2. 实现一个简易的HashMap

    实现一个键的类型为int,值的类型为int的HashMap 输入一个T,表示操作次数: 之后每行接一个操作,可以包括插入.删除.修改.查询.清空.判断是否有这个键: 因为是刚学完随手敲的,所以功能粗糙 ...

  3. Servlet.service() for servlet [appServlet] in context with path [/item] threw exception [Request processing failed

    以前犯过的一个小错误,不过忘记怎么修改了,所以还是记录下来好一点 严重: Servlet.service() for servlet [appServlet] in context with path ...

  4. virtualenv 个人指南

    virtualenv是解决一个机器上多个应用需要的Python版本不一致的问题,virtualenv就是用来为一个应用创建一套"隔离"的Python运行环境,解决了解决了不同应用间 ...

  5. springboot 多数据源之错误 HikariPool-1 - jdbcUrl is required with driverClassName.

    数据源连接报错: 之前在1.5.7的版本的时候用该数据源配置没问题,看如下所示 springboot1.5.7配置多数据源: datasource.master.url=jdbc:mysql://lo ...

  6. 将Hexo网站托管到Coding.net

    只需要注册coding.net,然后建立一个名为用户名+coding.me的仓库即可,需要注意的是 coding.net的pages仓库只能有一个master分支 开始使用 Coding Pages官 ...

  7. 递归加法(day1)

    题目:求1+2+-+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字以及条件判断语句(A?B:C). 使用函数指针 1 2 3 4 5 6 7 8 9 10 ...

  8. ReadHub项目Kotlin版开发指南(三、MVP架构)

    ReadHub项目Kotlin版转换指南(一.环境搭建) ReadHub项目Kotlin版转换指南(二.数据库和网络请求) ReadHub项目Kotlin版转换指南(三.MVP架构) Android ...

  9. Louis的「每周语文」

    说明:此专栏为Louis收录的经典语录及书影音标记,每周一更新. 成长的本质是变得复杂.当你的主观世界遇到客观世界,之间的那条沟,你掉进去,叫挫折,爬出来,叫成长. -- 语出罗振宇在奇葩说第四季的结 ...

  10. LitePal

      Litepal采用的是对象关系映射(ORM)模式   LitePal的配置工作. 1.添加依赖  compile 'org.litepal.android:core:1.3.2' 2.配置lite ...