2024年Web前端最全List集合之ArrayList(三)ArrayList总结,一名毕业三年的女程序媛面试头条经验

最后

中年危机是真实存在的,即便有技术傍身,还是难免对自己的生存能力产生质疑和焦虑,这些年职业发展,一直在寻求消除焦虑的依靠。

  • 技术要深入到什么程度?

  • 做久了技术总要转型管理?

  • 我能做什么,我想做什么?

  • 一技之长,就是深耕你的专业技能,你的专业技术。(重点)

  • 独立做事,当你的一技之长达到一定深度的时候,需要开始思考如何独立做事。(创业)

  • 拥有事业,选择一份使命,带领团队实现它。(创业)

一技之长分五个层次

  • 栈内技术 - 是指你的前端专业领域技术

  • 栈外技术 - 是指栈内技术的上下游,领域外的相关专业知识

  • 工程经验 - 是建设专业技术体系的“解决方案”

  • 带人做事 - 是对团队协作能力的要求

  • 业界发声 - 工作经验总结对外分享,与他人交流

永远不要放弃一技之长,它值得你长期信仰持有

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

主要内容包括html,css,html5,css3,JavaScript,正则表达式,函数,BOM,DOM,jQuery,AJAX,vue 等等。

// 注意以上的remove操作都会改变modCount值

System.out.println(al);

System.out.println(“====================================”);

// set(int index,E e) 修改集合某索引位置上的元素的值

al.set(1,111);

// get(int index) 获取集合上某索引位置的元素

System.out.println(al.get(1));

}

}

Iterator迭代器代码练习


import java.util.ArrayList;

import java.util.Iterator;

public class ArrayListIteratorTest {

public static void main(String[] args) {

/**

  • ArrayList集合对象的Iterator迭代器对象的基本用法

*/

ArrayList list = new ArrayList();

list.add(1);

list.add(2);

list.add(3);

list.add(4);

list.add(5);

// Collection接口继承了Iterable接口,所以它的实现类需要重写iterable方法

// ArrayList中对于iterator()方法的重写是: return new Itr();

// iterator()用于获取集合对象的迭代器对象

// 可以看出迭代器对象必须依赖于集合对象

Iterator iterator = list.iterator();// lastRet=-1,cursor=0

// Itr类实现了Iterator接口,所以需要重写Iterator接口中定义的方法

// hasNext():用于判断迭代器将要迭代的下一个元素是否存在

// Itr类有两个成员变量:lastRet,cursor。

// 其中lastRet是迭代器正在迭代的元素的索引(若没有正在迭代的元素,lastRet=-1),cursor是迭代器将要迭代的下一个元素的索引

// 则hasNext()内部实现就是判断cursor的值是否为size,若cursor=size,则说明lastRet已经迭代到size-1,即集合最后一个元素,无法继续迭代

boolean hasNext = iterator.hasNext();//lastRet=-1,cursor=0

// next():用于获取迭代器将要迭代的下一个元素

// cursor指向的元素就是迭代器将要返回的下一个元素。而由于next()动作会导致lastRet,cursor后移一位。

// 所以用一个中间量 int i = cursor 保存next动作前的cursor值

// next动作中:cursor = cursor + 1;即将cursor后移一位

// lastRet = i;即将lastRet指向后移前的cursor值

// return elementData[lastRet];即获取lastRet指向的元素,并返回

iterator.next();//lastRet=0,cursor=1

// remove():用于删除迭代器正在迭代的元素

// 即删除lastRet指向的元素(前提是lastRet!=-1,即删除一个元素,要保证被删除的元素存在)

// 内部实现:是调用迭代器对象对应的集合对象的remove(lastRet)方法

// 由于ArrayList对象删除集合元素后,底层数组元素会发生移位,来填补被删除的元素位置。

// 所以cursor指向lastRet的位置

// lastRet = -1; 因为lastRet指向的元素已经被删除了,所以lastRet没有指向的元素了。

iterator.remove();//lastRet=-1,cursor=0

// foreachRemaining(Consumer consumer): 遍历处理剩下的元素

// 从该方法的名字可以看出foreach指遍历,Remaining指剩下的,consumer指处理遍历的每个元素

// 即遍历处理剩下的元素

// 注意:该方法遍历元素的起始位置是iterator对象的cursor,

// 即如果iterator对象之前没有做过任何next(),remove()操作的话,foreachRemaining是从cursor=0开始遍历

// 如果iterator对象已经操作过next(),remove()的话,则foreachRemaining从迭代器实际cursor值开始遍历

// 另外需要注意的foreachRemaining方法对cursor和lastRet的处理 和next()是不同的

// next()是调用一次,对cursor加1,lastRet指向最新的cursor-1的位置

// foreahRemaining是调用一次,直接将cursor值设置为size,lastRet=size-1

iterator.forEachRemaining(System.out::println);

System.out.println(“====================================”);

/**

  • ArrayList集合对象的Iterator迭代器迭代过程中出现ConcurrentModificationException引发原因

  • 并发修改异常是指在迭代器迭代过程中,集合对象发生了结构化修改。

  • 简单点理解就是:迭代器迭代过程中,对应集合对象的modCount成员属性值被改变了。

  • modCount是定义在AbstractList抽象类中的,专门给子类如ArrayList继承的成员属性。

  • ArrayList的

  • add,remove,clear,retainAll(改变了集合的size属性)

  • || ensureCapacity,trimToSize(改变了集合的容量)

  • || sort,replaceAll(改变了集合的所有元素)

  • 操作都会改变modCount的值,这些操作统一称为ArrayList集合的结构化修改操作

*/

ArrayList list2 = new ArrayList();

list2.add(1);

list2.add(2);

list2.add(3);

list2.add(4);

list2.add(5);

/**

  • 那么迭代器的哪些方法可能抛出并发修改异常呢?即哪些迭代器动作算是迭代动作呢?

*/

// 注意当iterator1对象初始化时,已经保存了集合对象的modCount值到自己属性expectedModCount中

// iterator1迭代时,会实时比较modCount是否和expectedModCount相等

// 若相等,则说明集合对象没有发生结构化修改

// 若不相等,则说明集合对象发生了结构化修改

Iterator iterator1 = list2.iterator();

iterator1.next();//先next一下,保证remove()不会抛出非法状态异常,因为初始时,lastRet指向-1位置

list2.add(3);//此步操作回导致集合对象的modCount发生改变

iterator1.hasNext();

//iterator1.next();//java.util.ConcurrentModificationException

//iterator1.remove();//java.util.ConcurrentModificationException

//iterator1.forEachRemaining(System.out::println);//java.util.ConcurrentModificationException

/**

  • 从上面程序可以看出,只有hasNext()操作不会受到并发修改异常的影响

  • 而next,remove,foreachRemaining都要求方法执行中,集合对象不能发生结构化修改

*/

}

}

ListIterator迭代器代码联系


import java.util.ArrayList;

import java.util.ListIterator;

public class ArrayListListIteratorTest {

public static void main(String[] args) {

/**

  • ArrayList的ListIterator迭代器对象的基本用法

*/

ArrayList list = new ArrayList();

list.add(1);

list.add(2);

list.add(3);

list.add(4);

list.add(5);

// ArrayList除了可以生成Iterator迭代器对象外

// 还可以生成ListIterator迭代器对象。

// ArrayList自定义了ListIterator listIterator(int index); 内部是: return new ListItr(int index);

// 和ListIterator listIterator(); 内部是: return new ListItr(0);

// 这两个方法都能够获取ListIterator接口的实现类ListItr对象

// ListItr继承了Itr类,实现类ListIterable接口

// 由于ListItr继承了Itr,所以ListItr也有两个成员属性lastRet,cursor

// 当使用ListIterator listIterator(int index),其中index的值会被赋值给cursor

// 当使用ListIterator listIterator(),内部会默认将index设置为0,并赋值给cursor

ListIterator listIterator = list.listIterator(5);//lastRet=-1,cursor=5

// hasPrevious()方法 用于判断当前迭代器将要迭代的上一个元素

// 即判断 cursor是否等于0,如果cursor等于0了,则说明已经迭代到了集合的第一个元素,不能再往前迭代了

boolean hasPrevious = listIterator.hasPrevious();

// previous()方法 用于获取当前迭代器将要迭代的元素的上一个元素

// 由于cursor是将要迭代的元素,所以cursor-1是将要迭代的元素的上一个元素

// 内部实现:previous操作会将cursor-1指向的元素作为返回值,且将cursor=cursor-1,即lastRet,cursor都指向被返回的元素

listIterator.previous();

// set(E e)方法 即将当前正在迭代的元素的值改为e

// 内部实现:内部调用ArrayList对象的set(lastRet,e)方法,不影响lastRet,cursor指向

listIterator.set(55);

// add(E e)方法 即将e插入到cursor位置

// 内部实现:内部调用ArrayList对象的add(cursor,E e)方法,完成插入元素到指定索引处。

// 由于插入元素到cursor位置,导致cursor指向的元素后移了一位,所以cursor=cursor+1

// 而lastRet指向的元素要么是cursor-1,要么是curosr,要么是-1。所以插入元素都会导致lastRet指向的元素变更,所以将LastRet重置为-1

listIterator.add(45);

// nextIndex()方法用于获取cursor值,即将要迭代的元素索引

listIterator.nextIndex();

// previous()方法用于获取cursor-1值,即将要迭代的元素的上一个元素的索引

listIterator.previousIndex();

/**

  • ArrayList的ListIterator迭代器对象迭代过程中可能发生ConcurrentModificationException的方法

*/

ArrayList list1 = new ArrayList();

list1.add(1);

list1.add(2);

list1.add(3);

list1.add(4);

list1.add(5);

ListIterator listIterator1 = list1.listIterator(5);

list1.add(6);

listIterator1.hasPrevious();

//listIterator1.previous();//java.util.ConcurrentModificationException

//listIterator1.set(55);//java.util.ConcurrentModificationException

//listIterator1.add(12);//java.util.ConcurrentModificationException

listIterator1.nextIndex();

listIterator1.previousIndex();

/**

  • 通过上面测试可以发现ListIterator迭代器对象的previous,set,add方法中都会检查modCount,即集合对象是否结构化修改

  • 如果集合对象发生了结构化修改,就会抛出并发修改异常

  • 另外,需要注意ListIterator迭代器的对象是ListItr实现类对象,ListItr继承了Itr类,

  • 所以hasNext(),next(),remove(),foreachRemaining(Consumer c)也会被ListItr继承,同样的

  • ListIterator迭代器的next,remove,foreachRemaining也一样可能抛出并发修改异常

*/

/**

  • 对比ListIterator和Iterator迭代器的联系与却别

  • ListIerator的的实现类ListItr继承了Iterator的实现类Itr

  • Iterator只能顺序迭代,且只能单向迭代,一旦迭代到最后一个元素,迭代器就不能再次利用

  • ListIterator即可顺序迭代,也可以逆序迭代,即可以双向迭代,一旦迭代到第一个或最后一个元素,还可以next()或previous()继续反向迭代

  • Iterator只有hasNext(),next(),remove(),foreachRemaining(Consumer consumer)方法

  • ListIterator的实现类继承了Iterator的实现类,所以继承了Iterator所有方法,且还有hasPrevious(),previous(),add(E e),set(E e)

  • Iterator适用于所有集合,ListIterator只适用于List集合

*/

}

}

思考题

===

ArrayList的底层数据结构是什么?


ArrayList底层数据结构是Object[]数组。

ArrayList类定义了一个成员属性:Object[] elementData

ArrayList的元素是否可以是null?


可以。

因为ArrayList底层数据结构是Object[]类型数组,该数组可以存入任何引用类型对象,null也是引用类型对象。

ArrayList的元素的类型为什么可以不一致?


因为ArrayList底层数据结构是Object[]数组,所有只要存入的元素是引用类型即可,不要求每个元素类型一致。

ArrayList有几个扩容方案?扩容原理是什么?


ArrayList的扩容原理就是  创建一个新数组,该新数组的长度是扩容后容量,将老数组的元素复制到新数组中。

ArrayList提供了三种构造器,不同的构造器的扩容方案不同:

ArrayList(),无参构造器,初始时是空的Object[]数组,第一次add时,创建一个长度为10的Object[]数组,并将add的元素存入size(size初始值是0)位置,后size=size+1。非第一次add,且容量不足时(小于当前容量+1),扩容Math.max(当前容量+1,当前容量*1.5)

ArrayList(int initialCapacity)或者ArrayList(Collection c)有参构造器,如果initialCapacity=0.或者c是空集合,那么初始时是空的Object[]数组,否则是对应InitiailCapacity大小的空Object[]数组或者是对应c.toArray()的Object[]数组。后面add操作时,若

容量不足(小于当前容量+1),则扩容Math.max(当前容量+1,当前容量*1.5)

ArrayList的add方法可以自动扩容,有没有人为扩容的方法?


ArrayList的add操作可以扩容,包括add(E e),add(Collection c),add(int index, E e),add(int index,Collection c),以及 ensureCapacity(int minCapacity)

ArrayList的remove方法删除元素后会导致缩容吗?


不会,remove方法不会导致集合缩容

ArrayList有没有方法可以缩容?其实现原理什么?


ArrayList提供了trimToSize()方法将集合容量缩小为size,即有多少个元素,就给多少容量。

Arrays.copyOf(elementData,size)

ArrayList是否支持对象克隆?为什么?ArrayLsit的对象克隆是深克隆还是浅克隆?为什么?


支持,因为ArrayList实现了Cloneable接口,并重写了clone方法

ArrayList的对象克隆是浅克隆。

最后

中年危机是真实存在的,即便有技术傍身,还是难免对自己的生存能力产生质疑和焦虑,这些年职业发展,一直在寻求消除焦虑的依靠。

  • 技术要深入到什么程度?

  • 做久了技术总要转型管理?

  • 我能做什么,我想做什么?

  • 一技之长,就是深耕你的专业技能,你的专业技术。(重点)

  • 独立做事,当你的一技之长达到一定深度的时候,需要开始思考如何独立做事。(创业)

  • 拥有事业,选择一份使命,带领团队实现它。(创业)

一技之长分五个层次

  • 栈内技术 - 是指你的前端专业领域技术

  • 栈外技术 - 是指栈内技术的上下游,领域外的相关专业知识

  • 工程经验 - 是建设专业技术体系的“解决方案”

  • 带人做事 - 是对团队协作能力的要求

  • 业界发声 - 工作经验总结对外分享,与他人交流

永远不要放弃一技之长,它值得你长期信仰持有

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

主要内容包括html,css,html5,css3,JavaScript,正则表达式,函数,BOM,DOM,jQuery,AJAX,vue 等等。

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值