巧用RandomAccess接口,集合遍历性能提升几十倍

for (int i = 0; i < list.size(); i++) {

list.get(i);

}

}

方案二,使用迭代器来获取集合元素?

private void traverse(List list) {

for (Iterator iterator = list.iterator(); iterator.hasNext()😉 {

iterator.next();

}

}

方案验证

===============================================================

针对上述提出的2种方案,我们进行验证,因为我们开发中经常使用的List实现类是ArrayList和LinkedList。所以验证传入这2种集合类型时,验证集合遍历性能。

package com.nobody;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.LinkedList;

import java.util.List;

/**

  • @Description

  • @Author Mr.nobody

  • @Date 2021/4/25

  • @Version 1.0

*/

public class Demo {

public static void main(String[] args) {

// 集合大小

int ListSize = 200000;

// 初始化ArrayList集合

ArrayList arrayList = new ArrayList<>();

for (int i = 0; i < ListSize; i++) {

arrayList.add(i);

}

System.out.println(“ArrayList Type:”);

traverseWithFor(arrayList);

traverseWithIterator(arrayList);

// 初始化LinkedList集合

LinkedList linkedList = new LinkedList<>();

for (int i = 0; i < ListSize; i++) {

linkedList.add(i);

}

System.out.println(“LinkedList Type:”);

traverseWithFor(linkedList);

traverseWithIterator(linkedList);

}

private static void traverseWithFor(List list) {

long startTime = System.currentTimeMillis();

for (int i = 0; i < list.size(); i++) {

list.get(i);

}

System.out.println(“traverseWithFor:” + (System.currentTimeMillis() - startTime));

}

private static void traverseWithIterator(List list) {

long startTime = System.currentTimeMillis();

for (Iterator iterator = list.iterator(); iterator.hasNext()😉 {

iterator.next();

}

System.out.println(“traverseWithIterator:” + (System.currentTimeMillis() - startTime));

}

}

输出结果如下,发现集合类型是ArrayList时,使用for下标定位(方案一)遍历集合效率更高;集合类型是LinkedList时,使用迭代器(方案二)遍历集合效率更高。特别地,如果LinkedList集合量很大并且使用for下标遍历,效率极其差。

ArrayList Type:

traverseWithFor:9

traverseWithIterator:15

LinkedList Type:

traverseWithFor:35548

traverseWithIterator:12

RandomAccess 接口

==========================================================================

通过以上验证,发现不能单纯的使用其中一种方案来遍历传入的集合,因为传入参数的List的实现类是未知的。那我们可以判断传入参数的具体实现类,来决定使用哪种遍历算法不就可以了。

private static void traverse(List list) {

if (list instanceof ArrayList) {

for (int i = 0; i < list.size(); i++) {

list.get(i);

}

} else if (list instanceof LinkedList) {

for (Iterator iterator = list.iterator(); iterator.hasNext()😉 {

iterator.next();

}

}

}

以上是比较理想化的情况,如果List的实现类随着时间,会增多或者减少,那岂不是要经常修改此方法,增加或者减少instanceof的条件判断?

所以在JDK1.4之后,出现了RandomAccess接口,它是一个空的标记接口。

package java.util;

public interface RandomAccess {

}

它的作用是,如果一个集合的实现类实现了此标记接口,表明此实现类支持快速随机访问(通常是固定时间)。RandomAccess 接口的主要目的是允许一般的算法能更改其行为,从而在随机或连续访问列表时能提供良好的性能。

通俗讲,就是在随机访问或者顺序遍历集合时候,我们可以根据集合实现类是否实现了RandomAccess接口,来决定使用不同的遍历策略。官方鼓励,对于那些遍历呈现线性访问时间,而且随机访问是固定时间的集合类,推荐实现RandomAccess接口。

例如ArrayList类实现了RandomAccess接口,LinkedList类是没有实现RandomAccess接口的。

官方也说明了,如果集合类实现了RandomAccess接口,推荐使用for (int i=0, n=list.size(); i < n; i++)遍历,避免使用Iterator迭代器遍历集合。反之,如果集合类是Sequence List(例如LinkedList),则推荐使用迭代器。

package com.nobody;

import java.util.*;

/**

  • @Description

  • @Author Mr.nobody

  • @Date 2021/4/25

  • @Version 1.0

*/

public class Demo {

public static void main(String[] args) {

// 集合大小

int ListSize = 200000;

// 初始化ArrayList集合

ArrayList arrayList = new ArrayList<>();

for (int i = 0; i < ListSize; i++) {

arrayList.add(i);

}

System.out.println(“ArrayList Type:”);

traverseWithFor(arrayList);

traverseWithIterator(arrayList);

traverse(arrayList);

LinkedList linkedList = new LinkedList<>();

for (int i = 0; i < ListSize; i++) {

linkedList.add(i);

}

System.out.println(“LinkedList Type:”);

traverseWithFor(linkedList);

traverseWithIterator(linkedList);

traverse(linkedList);

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

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

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

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

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

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

img

总结

在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了

面试真题

Spring源码笔记

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
" style=“zoom: 33%;” />

总结

在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了

[外链图片转存中…(img-rnA9ap35-1713662850160)]

[外链图片转存中…(img-LVnmFu0x-1713662850160)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值