1.ArrayList

1.1 实现了Access接口

实现标记接口Access有以下特点

  • 目的是允许通用算法提供良好的性能
  • 当遍历方式不同,速度不同时,通常需要继承这个接口

1.2 ArrayList 的迭代器

1.2.1 Iterator

  • 继承Itrator接口
private class Itr implements Iterator<E>
  • hasNext()方法通过游标和数组长度进行比较判断
public boolean hasNext() {
return cursor != size;
}
  • next()接口,获取游标所在位置的元素,游标向后移动一个位置;
 public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];//设置lastRet为i,lastRet是锁定元素
}
  • remove()方法,主要经过了以下几个步骤:

    • 删除当前位置lastRet锁定位置的值;(ArrayList的remove方法的删除,其实是将数组元素移动1个位置重新copy)
    • 删除后cursor = lastRet,也就意味着将游标指向 锁定元素的位置;
    • 将锁定元素设置为-1;

      从上面的步骤可以看出:

      1.当iterator没有移动使用next()方法,lastRet是-1,调用ArrayList的remove方法会报错;

      2.并且使用iterator逐个删除元素的时候,必须在remove之前用next()方法移动游标,将锁定元素lastRet设置为当前i
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
} ======ArrayList 的remove方法======
public E remove(int index) {
rangeCheck(index); modCount++;
E oldValue = elementData(index); int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work return oldValue;
}

1.2.1 ListIterator

  • 1.继承Iterator实现类,并实现了ListIterator接口

    就是对iterator接口方法的扩充
 private class ListItr extends Itr implements ListIterator<E>
ListItr(int index) {
super();
cursor = index;
}
  • 2.previous方法 ,将游标cursor移动到前一个位置,并设置lastRet为当前的元素i;
     public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}
  • 3.set方法,根据lastRet的位置设置,不能在cursor为0时设置;add方法,是将ArrayList的元素从index+1拷贝重生成;
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
} public void add(E e) {
checkForComodification(); try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

1.3 SubList子列表

  • 获取ArrayList的区间进行操作,可以使用ArrayList的所有操作
pubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}

1.4 ArrayListSpliterator

1.ArrayList集合中获取

初始的index 是0,fence是-1
   ======== ArrayList ==========
@Override
public Spliterator<E> spliterator() {
return new ArrayListSpliterator<>(this, 0, -1, 0);
}
===== ArrayListSpliterator 构造函数 ====
ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
int expectedModCount) {
this.list = list; // OK if null unless traversed
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}

2.进行分栏操作

  进行二分操作,返回的是以index为首,中间值mid为fence的新的ArrayListSpliterator
 //fence大小为 list的size
public ArrayListSpliterator<E> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null : // divide range in half unless too small
new ArrayListSpliterator<E>(list, lo, index = mid,
expectedModCount);
}

3.forEachRemaining

就是将剩余的元素进行遍历

if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
if (lst.modCount == mc)
return;
}

4.主要的作用是当大数据list进行遍历处理时,可以进行切分

示例代码如下:

在实际使用中,可以用多线程处理

public class ArrayListTest {

    public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("wangwu");
list.add("zhaoliu");
list.add("job");
list.add("tom");
Spliterator<String> spliterator = list.spliterator();
Spliterator<String> s1 = spliterator.trySplit();
spliterator.forEachRemaining(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
s1.forEachRemaining(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
} }
========== 输出的结果 =============
zhaoliu
job
tom
zhangsan
wangwu

1.5 基本属性

1.ArrayList元素存储及扩容

  • 默认为空数组,也可通过构造函数传参,确定初始容量大小
  • Object 数组存储元素
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
  • Object数组进行扩容,首次add数据初始化最小为10
    private void ensureCapacityInternal(int minCapacity) {//传入最小的容量
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static final int DEFAULT_CAPACITY = 10;
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void grow(int minCapacity) { //将object数组进行扩容
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

总结一下:

1.ArrayList,底层是通过Object对象数组存储对象,并不是通过泛型数组存储;

2.默认初始化为空数组,首次初始化最小容量为10;

3.提供了iterator,和listIterator两个子类,用于遍历使用;

4.iterator遍历删除要先用next()移动游标,否则会报错;

5.ListIterator的set方法使用,必须要进行游标移动;

6.SubList是对ArrayList进行截取一部分进行操作;

List集合-01.ArrayList的更多相关文章

  1. C#语言基础——集合(ArrayList集合)

    集合及特殊集合 集合的基本信息: System.Collections 命名空间包含接口和类,这些接口和类定义各种对象(如列表.队列.位数组.哈希表和字典)的集合.System.Collections ...

  2. C#集合之ArrayList

    C#中之所以有集合这个东东,是因为数组的长度是固定的,而实际需求是,不确定未来这个“数组”的个数,故出现集合这个概念,因为集合的容量会随元素的增加曾倍数增长.C#中有2类常用集合:ArrayList, ...

  3. Java基础知识强化之集合框架笔记64:Map集合之ArrayList嵌套HashMap

    1. ArrayList集合嵌套HashMap集合并遍历.  需求:         假设ArrayList集合的元素是HashMap.有3个.         每一个HashMap集合的键和值都是字 ...

  4. C#重的数组、集合(ArrayList)、泛型集合(list<T>)三者比较及扩展延伸……

    本来我只想总结下数组.集合(ArrayList).泛型集合(list<T>)三者的比较的,可以一写下来要扩展的知识点有点多了,只能写一个小的知识点列表了如下: 1.数组.集合(ArrayL ...

  5. 集合框架-ArrayList,Vector,Linkedlist

    // ClassCastException 报错,注意,千万要搞清楚类型 * Vector的特有功能: * 1:添加功能 * public void addElement(Object obj) -- ...

  6. 转:C#常用的集合类型(ArrayList类、Stack类、Queue类、Hashtable类、Sort)

    C#常用的集合类型(ArrayList类.Stack类.Queue类.Hashtable类.Sort) .ArrayList类 ArrayList类主要用于对一个数组中的元素进行各种处理.在Array ...

  7. C#基础课程之四集合(ArrayList、List<泛型>)

    list泛型的使用 ArrayList list = new ArrayList(); ArrayList list = ); //可变数组 list.Add("我"); //Ad ...

  8. Java基础-集合框架-ArrayList源码分析

    一.JDK中ArrayList是如何实现的 1.先看下ArrayList从上而下的层次图: 说明: 从图中可以看出,ArrayList只是最下层的实现类,集合的规则和扩展都是AbstractList. ...

  9. C#中数组、集合(ArrayList)、泛型集合List<T>、字典(dictionary<TKey,TValue>)全面对比

    C#中数组.集合(ArrayList).泛型集合List<T>.字典(dictionary<TKey,TValue>)全面对比 为什么把这4个东西放在一起来说,因为c#中的这4 ...

随机推荐

  1. java实现第五届蓝桥杯猜字母

    猜字母 题目描述 把abcd-s共19个字母组成的序列重复拼接106次,得到长度为2014的串. 接下来删除第1个字母(即开头的字母a),以及第3个,第5个等所有奇数位置的字母. 得到的新串再进行删除 ...

  2. 用户管理命令-passwd

    passwd可以给用户设置密码或者修改密码,超级用户可以修改任何用户的密码,而且可以不遵守密码的复杂性原则,普通用户只能修改自己的密码,必须遵守密码的复杂性原则 passwd [选项] 用户名 常用选 ...

  3. 2018年全国多校算法寒假训练营练习比赛(第二场)H-了断局

    题目描述 既然是了断局了,大家就随便玩玩数字呗.已知一个数列前十项分别是{0, 1, 1, 2, 4, 7, 13, 24, 44, 81},小G不满足呀:我要更多的数!!!不给就不让你们玩了.小G会 ...

  4. Github 创建SSH密钥克隆仓库详解

    1.登录Github主页,点击任意一个repository,点击Clone or download,点击Use SSH 2.点击add a new pulbic key,创建公钥 3.下面图中的Tit ...

  5. C# .net framework .net core 3.1 请求参数校验, DataAnnotations, 自定义参数校验

    前言 在实际应用场景中我们常常要对接口的入参进行校验, 例如分页大小是否正确, 必填参数是否已经填写等等. 最简单的实现方式如下图, 这种在实际开发中代码过于冗余, 而且不灵活. 今天介绍一种统一参数 ...

  6. 如何在react中使用decorator

    2020-03-27 如何在react中使用decorator decorator目前都需要修改babel才能使用 说一下具体的操作方法 踩了一天的坑... 步骤1: yarn create reac ...

  7. centos 8分区方案

    https://www.cnblogs.com/yogurtwu/p/10717001.html https://zhuanlan.zhihu.com/p/126308255 常见目录解释 Linux ...

  8. Backup Database pubs to Disk='D:\DataSQL\pubs.bak' --->动态备份所有数据库

    备份数据库 在项目实施时,备份恢复数据库还是有必要的,自动或傻瓜式的操作比较方便,未测试,失业了,现在静不下心来,有机会要求再做这类操作时实现它,此处先收藏备用 /* <Dynamic SQL ...

  9. xdoj 2020校赛复盘

    平时写东西都不喜欢复盘,这肯定不是一个好习惯,感觉每次花好几个小时甚至好几天写题目然后没写出来也不去看题解是一种很蠢的行为( 花了这么久时间打校赛,虽然水平很low,数据结构也不太会用,还是记录一下自 ...

  10. opencv3.1.0 计算机中丢失 opencv_world310d.dll _vs2017解决方法

    ---------------------------opencv1.exe - 系统错误---------------------------无法启动此程序,因为计算机中丢失 opencv_worl ...