简介

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. [LC] 379. Design Phone Directory

    Design a Phone Directory which supports the following operations: get: Provide a number which is not ...

  2. Java入门级文件下载_学习笔记

    文件下载和上一篇文件上传很像,就不多说了,传一个我写的一个下载歌曲的代码: 下面是Servlet代码: public class DownLoadServlet extends HttpServlet ...

  3. python--防止SQL注入

    from pymysql import * def main(): # 创建Connextion连接 conn = connect(host='localhost', port=3306, user= ...

  4. python3多进程爬虫(第二卷)

    上卷中讲到,我有4个进程,可是我要同时爬取20+数据怎么办,很明显上卷的语法公式不可以,所以现在我引入线程池 现在看一下线程池的语法 看一下爬虫: 注意圈中重点

  5. ZOJ-1183-Scheduling Lectures

    可以用贪心求最小讲课次数,贪心策略也很好想,就是对于任意主题,能早讲就早讲.这种方案的讲课次数一定是最少的,但是不满意指标不一定是最小,然后再利用动态规划求在最少讲课次数前提下的最小不满意指标. 方法 ...

  6. Java IO: 并发IO

    原文链接 作者: Jakob Jenkov 译者: 李璟 有时候你可能需要并发地处理输入和输出.换句话说,你可能有超过一个线程处理输入和产生输出.比如,你有一个程序需要处理磁盘上的大量文件,这个任务可 ...

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

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

  8. etcd安装部署步骤

    我是通过yum直接安装的(yum install etcd -y),其生成的配置文件在/etc/etcd/etcd.conf. 这里分单机版和集群版来介绍配置项 单机配置 ETCD_DATA_DIR: ...

  9. PDCA理念融入软件测试

    PDCA理念融入软件测试    摘要:软件测试作为软件质量保障的重要手段,PDCA循环是全面质量管理所应遵循的科学程序.本文结合软件测试工作的特点,通过文档规范的方式,将PDCA的理念融入软件测试,提 ...

  10. Proto3使用指南

    这篇指南讲述如何使用Protocol Buffers来结构化你的Protocol Buffer数据,包括.proto文件语法以及如何从.proto文件生成你的访问类型.本文主要涵盖了proto3的语法 ...