纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

Java接口List Java源码解析之接口List

不会编程的派大星   2021-05-19 我要评论
想了解Java源码解析之接口List的相关内容吗不会编程的派大星在本文为您仔细讲解Java接口List的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Java接口List,java,List接口下面大家一起来学习吧

前言

List接口是Collection接口的三大接口之一其中的数据可以通过位置检索用户可以在指定位置插入数据List的数据可以为空可以重复我们来看看api文档是怎么说的:

在这里插入图片描述

一、List特有的方法

我们这里就只关注和Collection不同的方法主要有以下这些:

//在指定位置将指定的集合插入到当前的集合中
boolean addAll(int index, Collection<? extends E> c);

//这是一个默认实现的方法会通过Iterator的方式对每个元素进行指定的操作
default void replaceAll(UnaryOperator<E> operator) {
    Objects.requireNonNull(operator);
    final ListIterator<E> li = this.listIterator();
    while (li.hasNext()) {
        li.set(operator.apply(li.next()));
    }
}

//排序依据指定的规则对当前集合进行排序可以看到排序是通过Arrays这个工具类完成的
default void sort(Comparator<? super E> c) {
    Object[] a = this.toArray();
    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继承于Iterator主要增加了向前遍历的功能
ListIterator<E> listIterator();

//从指定位置开始返回一个ListIterator
ListIterator<E> listIterator(int index);

//返回一个子集合[fromIndex, toIndex)非结构性的修改返回值会反映到原表反之亦然
//如果原表进行了结构修改则返回的子列表可能发生不可预料的事情
List<E> subList(int fromIndex, int toIndex);

通过对上面方法的研究我们不难发现collection接口主要提供一些通常的方法而List接口则针对线性表的结构提供了对位置以及字表的操作

二、超级实现类AbstractList

我们先看看源文档是怎么来说AbstractList的要实现一个不可修改的集合只需要复写get和size方法如果要实现一个可以修改的集合还需要复写set方法如果要动态调整大小就必须实现add和remove方法

接下里我们一起来来看看源码吧!

//在AbstractCollection中add方法默认会抛出异常
//而在这里是调用了add(int index, E e)方法但这个方法也是没有实现的
//这里默认会把元素添加到末尾
public boolean add(E e) {
    add(size(), e);
    return true;
}

//同上这个只需要进行一次遍历即可
public boolean addAll(int index, Collection<? extends E> c) {
    //...   
}

接下里我们在继续看看其他几个方法这几个是与Iterator和ListIterator息息相关的在AbstractList中有具体的实现我们先来看看它是如何把集合转变成Iterator对象并支持foreach循环的吧

我们通过源码发现:在Iterator方法中是直接返回一个 Itr对象

public Iterator<E> iterator() {
    return new Itr();
}

其实我们很快也就会明白它是实现了一个内部类这个内部类实现了Iterator接口合理的处理hasNext、next、remove方法这个源码就不粘贴啦其中仅仅在remove时考虑了一下多线程问题有兴趣的可以自己去看看

我们来看看另一个吧–ListIterator吧他也是通过一个内部类是实现的

public ListIterator<E> listIterator() {
    return listIterator(0);
}
public ListIterator<E> listIterator(final int index) {
    rangeCheckForAdd(index);
    return new ListItr(index);
}

事实证明和我们想的一样AbstractList内部还定义了一个ListItr实现了ListIterator接口其实现也很简单就不粘贴源码啦

接下俩让我们来看看AbtractList是怎么利用这两个类来做事情的

//寻找一个元素首次出现的位置只需要从前往后遍历找到那个元素并返回其位置即可
public int indexOf(Object o) {
    ListIterator<E> it = listIterator();
    if (o==null) {
        while (it.hasNext())
            if (it.next()==null)
                return it.previousIndex();
    } else {
        while (it.hasNext())
            if (o.equals(it.next()))
                return it.previousIndex();
    }
    return -1;
}

//同理寻找一个元素最后一次出现的位置只需要从列表最后一位向前遍历即可
//看到listIterator(int index)方法是可以传递参数的这个我想我们都可以照着写出来了
public int lastIndexOf(Object o) {
    //...
}

//这个方法是把从fromIndex到toIndex之间的元素从集合中删除
//clear()方法也是调用这个实现的(我认为clear实现意义并不大因为在其上级AbstractCollection中已经有了具体实现)
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();
    }
}

在接下来让我们来说一说两个比较重要的内容一个是关于SubList另一个是关于equals和hascode的

三、SubList、equals和hascode

SubList并不是新建了一个list只是持有当前集合的引用然后控制了用户可以操作的范围所以在接口定义时就说明了其更改会直接反应到原集合中SubList是定AbstractList内部并且是AbstractList的基础上增加了对可选范围的控制

而equals和hascode的实现也关乎我们的使用在AbstractList中这两个方法不仅与其实例有关也和其内部包含的元素有关所以在定义数据元素时也应该复写这两个方法以保证程序的正确运行这里看下其源码加深一下印象吧

public boolean equals(Object o) {
    if (o == this)
        return true;
    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;
    }
    return !(e1.hasNext() || e2.hasNext());
}
public int hashCode() {
    int hashCode = 1;
    for (E e : this)
        //这里用到了数据元素的hashCode方法
        hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    return hashCode;
}

相关文章

猜您喜欢

  • Flutter 构建页面框架 Flutter 构建一个常用的页面框架

    想了解Flutter 构建一个常用的页面框架的相关内容吗岛上码农在本文为您仔细讲解Flutter 构建页面框架的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Flutter,构建页面,Flutter,构建页面框架下面大家一起来学习吧..
  • java树形菜单对象 java实现树形菜单对象

    想了解java实现树形菜单对象的相关内容吗张兵游勇在本文为您仔细讲解java树形菜单对象的相关知识和一些Code实例欢迎阅读和指正我们先划重点:java菜单对象,java树形菜单,java菜单下面大家一起来学习吧..

网友评论

Copyright 2020 www.fresh-weather.com 【世纪下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式