栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java几种遍历集合的方法(原理,复杂度,适用场合)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java几种遍历集合的方法(原理,复杂度,适用场合)

目录

1. 顺序存储和链式存储

1.1 顺序存储

1.2 链式存储

1.3 区别

2. Java常用的遍历方式

2.1 for循环遍历

2.2 Iterator迭代器

2.3 foreach循环

3. 实际使用中的最佳推荐


【写在前面】

今天对集合遍历做了一些了解和汇总,这里做个学习笔记,便于后续深入学习。

非原创,主要参考此文,可直接看原博文:Java遍历集合的几种方法分析

1. 顺序存储和链式存储

1.1 顺序存储

是存储结构类型中的一种,该结构是把逻辑上相邻的结点存储在物理位置上相邻的存储单元中,结点之间的逻辑关系由存储单元的邻接关系来体现。

可以根据元素的位置直接计算出内存地址,直接进行读取。读取一个特定位置元素的平均时间复杂度为O(1)。

通常只有基于数组实现的集合,才有这种特性。Java中以ArrayList为代表。

1.2 链式存储

链式存储结构,又叫链接存储结构。在计算机中用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。

不可以根据元素的位置直接计算出内存地址,只能按顺序读取元素。读取一个特定位置元素的平均时间复杂度为O(n)。

主要以链表为代表。Java中以linkedList为代表。

1.3 区别

(1)顺序存储需要开辟一个定长的空间,读写速度快,缺点不可扩充容量(如果要扩充需要开辟一个新的足够大的空间把原来的数据重写进去)。

(2)链式存储无需担心容量问题,读写速度相对慢些,由于要存储下一个数据的地址所以需要的存储空间比顺序存储大。

2. Java常用的遍历方式

2.1 for循环遍历

(1)原理:

基于计数器。遍历者在集合外部维护一个计数器,然后依次读取每一个位置的元素,当读取到最后一个元素后,停止。即需要按元素的位置来读取元素。

(2)复杂度:

对于顺序存储,因为读取特定位置元素的平均时间复杂度是O(1),所以遍历整个集合的平均时间复杂度为O(n)。而对于链式存储,因为读取特定位置元素的平均时间复杂度是O(n),所以遍历整个集合的平均时间复杂度为O(n2)(n的平方)。

(3)试用场合

   顺序存储:读取性能比较高。适用于遍历顺序存储集合。

   链式存储:时间复杂度太大,不适用于遍历链式存储的集合。

(4)示例:待补

2.2 Iterator迭代器

(1)原理:

每一个具体实现的数据集合,一般都需要提供相应的Iterator。相比于传统for循环,Iterator取缔了显式的遍历计数器。

所以基于顺序存储集合的Iterator可以直接按位置访问数据。

而基于链式存储集合的Iterator,正常的实现,都是需要保存当前遍历的位置。然后根据当前位置来向前或者向后移动指针。

(2)复杂度:

对于RandomAccess类型的集合来说,没有太多意义。

但是对于Sequential Access的集合来说,有很重大的意义,因为Iterator内部维护了当前遍历的位置,所以每次遍历,读取下一个位置并不需要从集合的第一个元素开始查找,只要把指针向后移一位就行了,遍历整个集合的时间复杂度就降低为O(n);

(3)适用场合

顺序存储:如果不太在意时间,推荐选择此方式。代码更加简洁,也防止了Off-By-One的问题。

链式存储:意义重大,平均时间复杂度降为O(n),这个优势很大,所以推荐此种遍历方式。

(4)示例:待补

2.3 foreach循环

(1)原理:

根据反编译的字节码可以发现,foreach内部也是采用了Iterator的方式实现,只不过Java编译器帮我们生成了这些代码。

(2)复杂度:

分析Java字节码可知,foreach内部实现原理,也是通过Iterator实现的,只不过这个Iterator是Java编译器帮我们生成的,所以我们不需要再手动去编写。但是因为每次都要做类型转换检查,所以花费的时间比Iterator略长。时间复杂度和Iterator一样。

(3)适用场合

 foreach只是让代码更加简洁了,但有一些缺点,就是遍历过程中不能操作数据集合(删除等),所以有些场合不使用。而且它本身就是基于Iterator实现的,但是由于类型转换的问题,所以会比直接使用Iterator慢一点,但是还好,时间复杂度都是一样的。所以怎么选择,参考上面两种方式,做一个折中的选择。

(4)示例:待补

3. 实际使用中的最佳推荐

Java数据集合框架中,提供了一个RandomAccess接口,该接口没有方法,只是一个标记。通常被List接口的实现使用,用来标记该List的实现是否支持Random Access。

一个数据集合实现了该接口,就意味着它支持Random Access,按位置读取元素的平均时间复杂度为O(1)。比如ArrayList。而没有实现该接口的,就表示不支持Random Access。比如linkedList。

所以,推荐的做法就是:如果想要遍历一个List,那么先判断是否支持Random Access,也就是 list instanceof RandomAccess。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/489482.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号