JDK8源码详解-util篇-AbstractList

本文深入解析了Java List抽象类的实现细节,包括其作为List接口的基类、数据结构(顺序表、链表)、构造器、内部迭代器Itr和ListItr的特点,以及子类如SubList和RandomAccessSubList的使用。重点介绍了并发修改的处理机制,以及常见的错误示例和操作方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

功能:该类提供了List相关类/接口的基础框架

开始版本JDK 1.2

注意
1. 本类为抽象
2. 可以存在相同的值,也可以为null
3. 数据结构:顺序表、链表

继承类AbstractCollection<E>

实现接口List<E>

所在包java.util

导入类:无

类声明

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

备注:本方法没有单独重写toString()方法,使用的是AbstractCollectiontoString()方法

框架图

image

属性

变量

保护变量

01.当前对象被修改的次数modCount
// 修改次数:初始为0
protected transient int modCount = 0;

方法

构造器

// 唯一构造器
protected AbstractList() {}

内部类

01.迭代器 Itr

注意
1. 通过迭代器中的remove()方法,对象的变量modCount和迭代器内部的expectedModCount均会改变,同步了修改,因此不会抛出ConcurrentModificationException异常
2. 使用本类的移除有关方法(非迭代器方法),只会改变对象的变量modCount,不会改变内部变量expectedModCount,导致对象和迭代器未同步,会导致ConcurrentModificationException异常
3. lastRet变量为当前元素的前一个元素下标,迭代器的remove()方法移除的是前一个元素(即上一次调用next()获取的元素),删除后后面的元素全部前移了一位,因此需要将当前元素的游标会前移一位,否则就跳过了原先此下标的元素
4. 迭代器的remove()方法移除前一个元素,这样不会破坏原对象遍历结果,而删除后面元素会影响遍历结果,因此若遍历中进行了增删改,遍历出来的结果和实际对象中的元素并不一定一致
5. 迭代器的remove()不能连续调用两次,如果不禁止连续删除而是直接给lastRetcursor减一原则上可以(开始仍然判断lastRet < 0),但会将已经遍历的元素删除容易使数据混乱,因此删除一次后会直接将lastRet会置为-1,而remove()方法开始就校验了lastRet不能小于0

// 源码
private class Itr implements Iterator<E> {
    // 游标后一个元素的下标
    int cursor = 0;
    // 上一个使用next()获取的元素下标,若元素被删除,此值重置为-1
    int lastRet = -1;
    // 当前集合被修改的次数
    int expectedModCount = modCount;
    // 判断游标后是否还有元素
    public boolean hasNext() {
        return cursor != size();
    }
    // 返回当前游标后的元素,实际调用的是get()方法
    public E next() {
        // 校验是否生成迭代器后有修改过值,若有则抛出ConcurrentModificationException异常
        checkForComodification();
        try {
            int i = cursor;
            E next = get(i);
            // 移动游标
            lastRet = i;
            cursor = i + 1;
            return next;
        } catch (IndexOutOfBoundsException e) {
            checkForComodification();
            throw new NoSuchElementException();
        }
    }
    // 移除元素
    public void remove() {
        // 比较了当前游标是否在第一个元素之前或刚进行过移除操作,是则直接报错(remove()方法移除的是当前游标前的元素)
        if (lastRet < 0)
            throw new IllegalStateException();
        // 校验修改次数是否与生成迭代器一致,不一致抛出ConcurrentModificationException异常        
        checkForComodification();
        try {
            // 调用集合的移除元素方法,移除的是当前游标前的元素
            AbstractList.this.remove(lastRet);
            
            if (lastRet < cursor)
                cursor--;
            // 移除元素后此值设置为-1,只要调用了next()移动了游标此处就不再是-1,而连续删除不会修改lastRet,仍是-1
            lastRet = -1;
            // 修改集合的修改次数并同步至迭代器(就是这里使得通过迭代器移除元素不会报错)
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException e) {
            throw new ConcurrentModificationException();
        }
    }
    // 校验修改次数是否与生成迭代器一致,不一致则抛出ConcurrentModificationException异常
    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}
// 错误示例1:游标未移动就删除元素
@Test
void contextLoads3() {
    List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    list.add("6");
    list.add("7");
    list.add("8");
    list.add("9");
    list.add("10");
    
    Iterator<String> it = list.iterator();
    // 还未进行游标移动,游标前无元素,抛出java.lang.IllegalStateException异常
    it.remove();
}    
// 错误示例2:连续调用迭代器移除方法
@Test
void contextLoads() {
    List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    list.add("6");
    list.add("7");
    list.add("8");
    list.add("9");
    list.add("10");

    Iterator<String> it = list.iterator();
    it.next();
    it.next();
    it.next();
    it.next();
    // 此处已设置lastRet为-1
    it.remove();
    // lastRet为-1,抛出java.lang.IllegalStateException异常java.lang.IllegalStateException
    it.remove();
}
// 错误示例3:生成迭代器后调用对象的删除方法(增加方法一样)
@Test
void contextLoads() {
    List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    list.add("6");
    list.add("7");
    list.add("8");
    list.add("9");
    list.add("10");

    Iterator<String> it = list.iterator();
    it.next();
    list.remove(0);
    // 抛出ConcurrentModificationException异常
    it.next();
}

02.List迭代器 ListItr

注意
1. 本迭代器继承于Iterator,单独为List集合提供了一些迭代器方法
2. 本迭代器并非游标固定在两端,而是将游标初始化在传输的集合下标前,传输0则从将游标放于开头
3. 除却迭代器通有的hasNext()next()remove()及一些校验方法,增加了适用于集合的hasPreviousprevious()nextIndex()previousIndex()set()add()方法
4. 集合原有的add()方法会使得modCount++,而迭代器增加的add()同步了修改次数,set()两者均未对modCount变量操作,效果一致,但若有些集合实现类对set()进行了修改使得modCount改变仍会对迭代器有影响,因此建议优先使用迭代器内的修改元素方法
5. set()remove()方法均在开始时校验了lastRet变量不为-1,因此这两个操作中间必须进行next()操作,原因仍是连续操作会对已经遍历的元素产生影响容易使数据混乱,而add()方法不会对已遍历过的元素产生影响则未判断

// 源码
private class ListItr extends Itr implements ListIterator<E> {
    // 构造器,根据指定下标放置游标
    ListItr(int index) {
        cursor = index;
    }
    // 游标之前是否还有元素,当前游标位置为0则表示之前没有元素
    public boolean hasPrevious() {
        return cursor != 0;
    }
    // 获取前一个元素
    public E previous() {
        checkForComodification();
        try {
            int i = cursor - 1;
            E previous = get(i);
            lastRet = cursor = i;
            return previous;
        } catch (IndexOutOfBoundsException e) {
            checkForComodification();
            throw new NoSuchElementException();
        }
    }
    // 获取游标后一个元素下标,即 cursor
    public int nextIndex() {
        return cursor;
    }
    // 获取游标前一个元素下标,即 cursor - 1
    public int previousIndex() {
        return cursor-1;
    }
    // 修改元素方法,同原迭代器的remove不同,此方法未改变lastRet变量,因此可以连续修改元素,只是修改的为同一个元素
    // 本方法虽然进行了修改次数同步,到实际有没有增加此处,与集合实现类的set()方法有关
    public void set(E e) {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            AbstractList.this.set(lastRet, e);
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
    // 本方法与原迭代器的remove一样,操作后变更了lastRet为-1,因此不能连续进行add操作,
    // 本方法同步了修改次数,不会直接导致ConcurrentModificationException异常
    public void add(E e) {
        // 校验是否在生成迭代器后有进行集合的修改操作(一般为add操作)
        checkForComodification();
        try {
            int i = cursor;
            AbstractList.this.add(i, e);
            lastRet = -1;
            cursor = i + 1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}
// 错误示例
@Test
void contextLoads() {
    List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    ListIterator<String> iterator = list.listIterator();
    iterator.next();
    iterator.remove();
    iterator.add("11");
    // 连续调用了remove()和set()方法,虽然中间存在一个add()方法,但未调用next(),抛出了java.lang.IllegalStateException异常
    iterator.set("0");
}

03.提供给截取元素的集合(未实现RandomAccess) SubList

注意
1. 本集合内部类继承AbstractList,因此本类的实现类调用subList()返回的集合对象不能转换为具体实现类的类型
2. 本方法中途也不允许对集合使用非本类的add()remove()方法,不建议使用非本类的set()方法
3. 本方法重写了get()方法,虽然看似是截取了原集合,但其实只是修改了获取方法,虽然本方法内的add()remove()set()get()等方法的下标针对的是截取后的集合,但是对象的指向还是原集合对象,因此增删改也会影响到原集合对象
4. 本方法的修改、移除等操作底层实际调用的是AbstractList的方法,本类的方法仅仅是进行了一些其他的处理,具体实现可以查看AbstractList对应方法详细解析

// 源码
class SubList<E> extends AbstractList<E> {
    // 储存传入需截取的集合
    private final AbstractList<E> l;
    // 储存起始截取下标
    private final int offset;
    // 储存需截取的元素数量(终止-起始)
    private int size;
    // 构造器,需传入需截取的集合对象,截取起始位置,截取终止位置
    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
        // 校验下标,起始不能小于0,终止不能大于集合长度,起始不能大于终止
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > list.size())
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
        l = list;
        offset = fromIndex;
        size = toIndex - fromIndex;
        this.modCount = l.modCount;
    }
    // 设置截取后的集合指定下标的元素
    public E set(int index, E element) {
        rangeCheck(index);
        checkForComodification();
        // 此处下标需增加起始下标位置,因为集合未去除之前和之后的元素
        return l.set(index+offset, element);
    }
    // 获取截取后的集合指定下标的元素
    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        // 此处下标需增加起始下标位置,因为集合未去除之前和之后的元素
        return l.get(index+offset);
    }
    // 获取截取后集合的元素个数
    public int size() {
        checkForComodification();
        return size;
    }
    // 给截取后的集合指定下标新增元素
    public void add(int index, E element) {
        rangeCheckForAdd(index);
        checkForComodification();
        // 此处下标需增加起始下标位置,因为集合未去除之前和之后的元素
        l.add(index+offset, element);
        this.modCount = l.modCount;
        // 增加截取后集合的元素个数
        size++;
    }
    // 移除截取后的集合指定下标的元素
    public E remove(int index) {
        rangeCheck(index);
        checkForComodification();
        E result = l.remove(index+offset);
        this.modCount = l.modCount;
        size--;
        return result;
    }
    // 移除截取后的集合指定范围的元素
    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        l.removeRange(fromIndex+offset, toIndex+offset);
        this.modCount = l.modCount;
        // 减少截取后集合的元素个数
        size -= (toIndex-fromIndex);
    }
    // 给截取后的集合新增指定集合内的全部元素
    // 本方法调用的addAll(int index, Collection<? extends E> c)方法
    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }
    // 给截取后的集合以指定下标为起始,新增指定集合内的全部元素
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        int cSize = c.size();
        if (cSize==0)
            return false;
        checkForComodification();
        l.addAll(offset+index, c);
        this.modCount = l.modCount;
        size += cSize;
        return true;
    }
    // 给截取后的集合生成List迭代器,实际生成的是AbstractList的List迭代器
    public Iterator<E> iterator() {
        return listIterator();
    }
    // 给截取后的集合生成以指定下标前为游标起始位置的List迭代器,实际生成的是AbstractList的List迭代器
    public ListIterator<E> listIterator(final int index) {
        checkForComodification();
        rangeCheckForAdd(index);
        return new ListIterator<E>() {
            // 此处下标需增加起始下标位置,因为集合未去除之前和之后的元素
            private final ListIterator<E> i = l.listIterator(index+offset);
            // 游标后是否有元素
            public boolean hasNext() {
                return nextIndex() < size;
            }
            // 获取游标后的元素,若游标后没有元素抛出NoSuchElementException异常
            public E next() {
                if (hasNext())
                    return i.next();
                else
                    throw new NoSuchElementException();
            }
            // 游标前是否有元素
            public boolean hasPrevious() {
                return previousIndex() >= 0;
            }
            // 获取游标前的元素,若游标前没有元素抛出NoSuchElementException异常
            public E previous() {
                if (hasPrevious())
                    return i.previous();
                else
                    throw new NoSuchElementException();
            }
            // 获取游标后一个元素的下标,需要减去起始元素下标,因为集合未去除之前和之后的元素
            public int nextIndex() {
                return i.nextIndex() - offset;
            }
            // 获取游标前一个元素的下标,需要减去起始元素下标,因为集合未去除之前和之后的元素
            public int previousIndex() {
                return i.previousIndex() - offset;
            }
            // 移除元素,同步了修改次数,调用的方法有校验lastRet,不能连续调用
            public void remove() {
                i.remove();
                SubList.this.modCount = l.modCount;
                // 减少截取后集合的元素个数
                size--;
            }
            // 修改元素
            public void set(E e) {
                i.set(e);
            }
            // 新增元素,同步了修改次数,调用的方法有校验lastRet,不能连续调用
            public void add(E e) {
                i.add(e);
                SubList.this.modCount = l.modCount;
                // 增加截取后集合的元素个数
                size++;
            }
        };
    }
    // 截取当前集合指定范围的元素
    public List<E> subList(int fromIndex, int toIndex) {
        return new SubList<>(this, fromIndex, toIndex);
    }
    // 校验集合下标,下标可以等于集合个数,用于移除、修改元素,最后一位下标是size-1,size位置没有元素
    private void rangeCheck(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    // 校验集合下标,下标不能等于集合个数,用于新增相关校验,最后一位下标是size-1,可以在size位置新增元素
    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    // 校验集合下标异常信息
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }
    // 校验迭代器生成后集合是否提供非迭代器方法修改元素(一般为新增和移除)
    private void checkForComodification() {
        if (this.modCount != l.modCount)
            throw new ConcurrentModificationException();
    }
}

04.提供给截取元素的集合(实现RandomAccess) RandomAccessSubList

注意
1. 本类继承了SubList,实际上还是调用了未实现RandomAccess接口时调用的内部类生成集合
2. 本类为List的底层类,未进行RandomAccess实现的特别区分,仅留下了框架,实现类若需不同处理需要重写此内部类

拓展RandomAccess是一个标志接口,对于一些方法可以通过此标识判断其是否支持快速随机访问

// 源码
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    // 继承了SubList,调用的是SubList的构造器
    RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
        super(list, fromIndex, toIndex);
    }
    // 继承了SubList,调用的是SubList的构造器
    public List<E> subList(int fromIndex, int toIndex) {
        return new RandomAccessSubList<>(this, fromIndex, toIndex);
    }
}

保护方法

01.移除指定下标范围的元素 removeRange(int fromIndex, int toIndex)

参数
1. fromIndex —— 起始下标
2. toIndex —— 终止下标

// 源码
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();
    }
}

抽象方法

01.获取指定下标的元素 get(int index)

// 源码
abstract public E get(int index);

私有方法

01.校验下标是否超过集合下标范围 rangeCheckForAdd(int index)

参数index —— 需要校验的下标

备注:超过集合下标范围有两种情况 —— 小于0和大于集合长度

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

02.超出下标异常信息 outOfBoundsMsg(int index)

参数index —— 校验出现异常信息的只当下标

备注:信息格式 —— Index: 指定下标, Size: 集合长度

// 源码
private String outOfBoundsMsg(int index) {
    return "Index: "+index+", Size: "+size();
}
// 示例
@Test
void contextLoads() {
    List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    // Index: 7, Size: 5
    list.add(7,"10");
}

公有方法

01.新增元素 add(E e)

参数e —— 增加的元素

注意
1. 此新增元素方法调用的是add(int index, E element),指定的下标为集合长度(下标从0开始,长度从1开始),长度即最后一个元素后一位的下标
2. 本方法调用的add(int index, E element)是必须重写,未重写会抛出UnsupportedOperationException异常

// 源码
public boolean add(E e) {
    add(size(), e);
    return true;
}

02.新增元素到指定下标 add(int index, E element)

参数
1. index —— 新增元素的指定下标
2. element —— 新增的元素

注意:本方法必须重写,未重写会抛出UnsupportedOperationException异常

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

03.设置指定下标的元素为指定元素 set(int index, E element)

参数
1. index —— 修改的元素下标
2. element —— 修改为的元素

注意:本方法必须重写,未重写会抛出UnsupportedOperationException异常

// 源码
public E set(int index, E element) {
    throw new UnsupportedOperationException();
}

04.移除指定下标的元素 remove(int index)

参数index —— 移除元素的下标

注意:本方法必须重写,未重写会抛出UnsupportedOperationException异常

// 源码
public E remove(int index) {
    throw new UnsupportedOperationException();
}

05.获取指定元素第一次出现下标 indexOf(Object o)

参数o —— 需获取的元素

注意
1. 获取的是集合中指定元素第一次出现的下标
2. 返回-1表示没有找到指定元素

补充previousIndex() —— 返回游标前一个元素的下标,游标开始时在第一个元素前,调用next()后游标后移

// 源码
public int indexOf(Object o) {
    ListIterator<E> it = listIterator();
    if (o==null) {
        // 如果指定元素为null需要单独比较,直接使用equals会空指针
        while (it.hasNext())
            if (it.next()==null)
                return it.previousIndex();
    } else {
        while (it.hasNext())
            // 此处已调用了next(),游标已后移,因此返回的下标为游标的前一个元素下标
            if (o.equals(it.next()))
                return it.previousIndex();
    }
    return -1;
}

06.获取指定元素最后一次出现的下标 lastIndexOf(Object o)

参数o —— 需获取的元素

补充
1. listIterator(size()) —— 创建一个开始游标在最后一个元素之后的迭代器
2. it.hasPrevious() —— 判断当前游标前面有没有元素
3. it.nextIndex() —— 获取当前游标后一位的元素下标 (此处是逆序的迭代器,因此要返回游标后的下标),调用it.previous()后游标前移
4. 以上这些方法在本类中有实现,后续有说明
5. 该方法获取的是最后一次出现下标,因此创建迭代器的游标在最后,反向遍历
6. 该方法未找到指定元素返回-1

// 源码
public int lastIndexOf(Object o) {
    ListIterator<E> it = listIterator(size());
    if (o==null) {
        // 如果指定元素为null需要单独比较,直接使用equals会空指针
        while (it.hasPrevious())
            if (it.previous()==null)
                return it.nextIndex();
    } else {
        while (it.hasPrevious())
            // 此处已调用了previous(),游标已后移,因此返回的下标为游标的前一个元素下标
            if (o.equals(it.previous()))
                return it.nextIndex();
    }
    return -1;
}

07.清空集合 clear()

注意
1. 本方法调用移除指定下标范围的元素,开始下标为0,结束下标为集合元素个数
2. 本方法实际上是一个一个元素移除的

// 源码
public void clear() {
    removeRange(0, size());
}

08.在指定下标新增指定集合内全部元素 addAll(int index, Collection<? extends E> c)

参数
1. index —— 新增集合元素的起始下标
2. c —— 新增的集合

注意
1. 此方法实际调用的是add(int index, E element),此方法必须重写,否则会抛出UnsupportedOperationException异常
2. 本方法是循环全部指定集合进行多次元素插入实现的,因此重复元素也会插入,不会去重

// 源码
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;
}

09.生成当前集合的迭代器 iterator()

注意:此处生成的迭代器为本类中的迭代器内部类

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

10.生成当前集合的List迭代器 listIterator()

注意
1. 此处生成的迭代器为本类中的List迭代器内部类
2. 指定游标位置设置在集合开头便于遍历全部元素

// 源码
public ListIterator<E> listIterator() {
    return listIterator(0);
}

11.生成当前集合指定下标前为起始位的List迭代器 listIterator(final int index)

注意:此处生成的迭代器为本类中的List迭代器内部类

// 源码
public ListIterator<E> listIterator(final int index) {
    // 校验指定下标是否小于0或超过集合长度
    rangeCheckForAdd(index);
    return new ListItr(index);
}

12.截取集合指定范围内的元素 subList(int fromIndex, int toIndex)

参数
1. fromIndex —— 起始下标
2. toIndex —— 终止下标

注意:本方法返回的集合虽然看似是截取了原集合的一部分,但其实只是修改了get()等方法,返回的对象仍然是原集合对象,因此对返回的集合进行修改仍会变更原集合

补充
1. RandomAccess是一个标志型的接口,内部无内容也无注释
2. 根据本类是否实现了RandomAccess接口匹配不同的处理,主要用于不同的实现类使用效率更高的处理方法
3. 本类为List的底层类,未进行RandomAccess实现的特别区分,因此本类无论是否实现了RandomAccess,均返回的是SubList内部类,但此类的实现类ArrayList实现了此接口,而LinkedList则没有实现此接口

// 源码
public List<E> subList(int fromIndex, int toIndex) {
    return (this instanceof RandomAccess ?
            new RandomAccessSubList<>(this, fromIndex, toIndex) :
            new SubList<>(this, fromIndex, toIndex));
}
// 示例
@Test
void contextLoads5() {
    List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("5");
    List<String> list1 = list.subList(1, 3);
    // [2, 3]
    System.out.println("截取后的集合" + list1);
    // [1, 2, 3, 4, 5]
    System.out.println("原集合:" + list.toString());
    
    list1.set(0,"11");
    // [11, 3]
    System.out.println("截取后的集合" + list1);
    // [1, 11, 3, 4, 5]
    System.out.println("原集合:" + list.toString());
    
    list1.add("22");
    // [11, 3, 22]
    System.out.println("截取后的集合" + list1);
    // [1, 11, 3, 22, 4, 5]
    System.out.println("原集合:" + list.toString());
    
    list1.remove(2);
    // [11, 3]
    System.out.println("截取后的集合" + list1);
    // [1, 11, 3, 4, 5]
    System.out.println("原集合:" + list.toString());
}

13.比较方法 equals(Object o)

参数o —— 比较的对象

// 源码
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();
        if (!(o1==null ? o2==null : o1.equals(o2)))
            return false;
    }
    return !(e1.hasNext() || e2.hasNext());
}

14.哈希值 hashCode

计算方法31 * 当前哈希值 + 元素哈希值(null为0),当前哈希值随着循环不断累积,首位为1

// 源码
public int hashCode() {
    int hashCode = 1;
    for (E e : this)
        hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
    return hashCode;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值