List集合之ArrayList(三)ArrayList总结

al.add(new String(“ABC”));

al.add(1);

al.add(1);

al.add(true);

al.add(true);

// ArrayList集合元素有序,可重复

System.out.println(al);//[ABC, 1, 1, true, true]

// ArrayList集合元素有索引

System.out.println(al.get(0));//ABC

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

// size()方法用于获取集合元素个数,即ArrayList对象的属性size值。注意size不是ArrayList的容量

System.out.println(al.size());

// isEmpty()方法用于判断集合是否有元素,即ArrayList对象的size是否为0,若为0返回true,反之返回false

System.out.println(al.isEmpty());

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

// ArrayList没有提供方法去获取集合的容量,但是有方法改变集合容量大小

// 缩容 trimToSize(),即将集合容量变为最小容量,即size大小。

//注意该操作会变更modCount值,即在迭代器迭代过程中,不能使用该方法

al.trimToSize();

// 扩容 ensureCapacity(int minCapacity),即将容量扩容到minCapacity大小,前提minCapacity比当前集合容量大

//注意该操作会变更modCount值,即在迭代器迭代过程中,不能使用该方法

al.ensureCapacity(10);

// foreach(Consumer consumer)可以遍历处理集合元素

// 注意foreach过程中,不能有改变集合modCount值的动作

al.forEach(data-> System.out.println(data));

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

// ArrayList实现了Cloneable接口,重写了clone方法,所以具备对象克隆功能

ArrayList clone = (ArrayList) al.clone();

System.out.println(clone);//[ABC, 1, 1, true, true]

// Java中对象克隆分为深克隆和浅克隆,

// 浅克隆是指克隆对象的引用类型变量的值(引用)和原对象一致。

// 深克隆是指克隆对象的引用类型变量的值(引用)和原对象不一致,但是变量指向的对象的内容一致

// ArrayList重写的clone方法是浅克隆,即克隆对象和原对象的elementData成员变量指向的数组对象是同一个对象

System.out.println(clone.get(0) == al.get(0));

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

// ArrayList支持将集合转成数组

// 方式1:toArray()方法,直接将集合转成Object[]数组,

// 注意这里不是直接将ArrayList对象的elementData属性返回,而是返回Arrays.copyOf(elementData,size)

Object[] array = al.toArray();

// 方式2:toArray(T[] a),外部传入一个数组类型对象,一般来说传入一个空的数组即可,

al.toArray(new Object[0]);

// 如果传入一个数组的长度大于集合元素个数,且数组有元素值,则可能会出现不好的效果

Object[] objects = new Object[10];

objects[9]=9;

al.toArray(objects);

System.out.println(Arrays.toString(objects));

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

// ArrayList获取元素索引

// indexOf(E e),获取某值在集合顺序equals比较元素第一次true的索引

System.out.println(al.indexOf(“ABC”));

// indexOf(E e),当某值在集合元素中不存在时返回-1

System.out.println(al.indexOf(null));

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

// lastIndexOf(E e),获取某值在集合逆序equals比较元素第一次true的索引

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

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

// contains(E e)即ArrayList集合是否包含有equals某值的元素

// 内部实现时return indexOf(o) >= 0;

al.contains(1);

// retainAll(Collection c),只保留ArrayList集合中 和c集合有交集的元素。

// 注意该操作会改变modCount值,所以在迭代器迭代过程中不能使用该方法操作ArrayList集合

HashSet hs = new HashSet();

hs.add(1);

hs.add(“ABC”);

hs.add(222);

al.retainAll(hs);

System.out.println(al);

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

// sort(Comparator con) 排序集合元素

// 注意此操作过程中不能有改变集合modCount的其他操作同时进行

// 注意此操作完成后,会改变modCount值

al.sort((o1,o2)->o1.toString().length()-o2.toString().length());

System.out.println(al);

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

// replaceAll(UnaryOperator uo),对集合元素做批量操作

// 注意此操作过程中不能有改变集合modCount的其他操作同时进行

// 注意此操作完成后,会改变modCount值

al.replaceAll(obj->obj+“123”);

System.out.println(al);

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

// 插入元素

// 分为两大类四小种

// 1.在集合元素尾部插入

// 1.1 尾部插入一个元素

al.add(12);//[1123, 1123, ABC123,12]

// 1.2 尾部插入多个元素

al.addAll(hs);//[1123, 1123, ABC123,12,1,ABC,222]

// 2.在集合指定索引处插入

// 2.1 指定索引处插入一个元素

al.add(2,22);//[1123, 1123, 22, ABC123,12,1,ABC,222]

// 2.2 指定索引处插入多个元素

al.addAll(2,hs);//[1123, 1123,1, ABC, 222, 22, ABC123,12,1,ABC,222]

// 注意add操作会改变modCount值

System.out.println(al);

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

// remove(E e),删除集合中第一个equals给定值的元素

al.remove(“ABC”);//[1123, 1123, 1, 222, 22, ABC123, 12, 1, ABC, 222]

// remove(int index) 删除指定索引处的元素

al.remove(1);//[1123, 1, 222, 22, ABC123, 12, 1, ABC, 222]

// removeAll(Collection c) 只保留ArrayList集合中 和c集合非交集的元素

al.removeAll(hs);//[1123, 22, ABC123, 12]

// removeIf(Predicate p) 删除掉符合predicate test要求的元素

al.removeIf(obj->obj.toString().length()>2);//[22, 12]

// 注意以上的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();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

前端面试题汇总


前端面试题是我面试过程中遇到的面试题,每一次面试后我都会复盘总结。我做了一个整理,并且在技术博客找到了专业的解答,大家可以参考下:

由于篇幅有限,只能分享部分面试题,完整版面试题及答案可以【点击我】阅读下载哦~

感悟

**

前端面试题汇总


前端面试题是我面试过程中遇到的面试题,每一次面试后我都会复盘总结。我做了一个整理,并且在技术博客找到了专业的解答,大家可以参考下:

由于篇幅有限,只能分享部分面试题,完整版面试题及答案可以【点击我】阅读下载哦~

感悟

春招面试的后期,运气和实力都很重要,自己也是运气比较好,为了回馈粉丝朋友们(毕竟自己也玩了这么久哈哈哈),整理个人感悟和总结以上。最后祝愿大家能够收获理想offer!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值