Java中集合类遍历性能 系统管理员 2022-05-09 01:50 118阅读 0赞 ### 集合元素在内存如何存放 ### 数据元素在内存中,主要有2种存储方式: 1、顺序存储,Random Access(或直接存储,Direct Access): 这种方式,相邻的数据元素存放于相邻的内存地址中,整块内存地址是连续的。可以根据元素的位置直接计算出内存地址,直接进行读取。读取一个特定位置元素的平均时间复杂度为O(1)。这种数据结构插入和删除时比较麻烦,查询比较方便。正常来说,只有基于数组实现的集合,才有这种特性。Java中以ArrayList为代表; 2、链式存储,Sequential Access: 这种方式是将数据元素放在独立的空间中,在内存中每个元素的内存地址都不要求是相邻的。所以每个元素中需要保存下一个元素的索引,即下一个元素的内存地址。所以这种数据结构插入和删除比较方便,但是查找很麻烦,要从第一个开始遍历,因为它无法根据元素的位置直接计算出内存地址,只能按顺序读取元素。读取一个特定位置元素的平均时间复杂度为O(n)。主要以链表为代表。Java中以LinkedList为代表; ### Java集合遍历方式 ### 1)传统的for循环遍历基于计数器 遍历者自己在集合外部维护一个计数器,然后依次读取每一个位置的元素,直到读取到最后一个元素后。主要就是需要按元素的位置来读取元素,适合于遍历顺序存储的数据结构; for (int i = 0; i < list.size(); i++) { list.get(i); } 2)迭代器遍历Iterator Iterator本来是OO的一个设计模式,主要目的就是屏蔽不同数据集合的特点,统一遍历集合的接口。从结构上可以看出,迭代器模式在客户与容器之间加入了迭代器角色。迭代器角色的加入,就可以很好的避免容器内部细节的暴露,而且也使得设计符号“单一职责原则”; 每一个具体实现的数据集合,一般都需要提供相应的Iterator。相比于传统for循环,Iterator取代了显式的遍历计数器。所以基于顺序存储集合的Iterator可以直接按位置访问数据。而基于链式存储集合的Iterator,正常的实现都是需要保存当前遍历的位置,然后根据当前位置来向前或者向后移动指针 迭代器模式的写法如下: Iterator iterator = list.iterator(); while (iterator.hasNext()) { iterator.next(); } 3)foreach循环遍历 foreach内部也是采用了Iterator的方式实现,根据反编译的字节码可以发现,foreach内部也是采用了Iterator的方式实现,只不过Java编译器帮我们生成了这些代码 优点:代码简洁,不易出错 缺点:只能做简单的遍历,不能在遍历过程中操作(删除、替换)数据集合 for (ElementType element : list) { } ### 遍历性能 ### 1)传统的for循环遍历基于计数器 ArrayList按位置读取的代码:直接按元素位置读取 public E get(int index) { rangeCheck(index); return elementData(index); } E elementData(int index) { return (E) elementData[index]; } LinkedList按位置读取的代码:如果index小于容量的一半,则从头开始查找,否则从尾部开始查找 public E get(int index) { checkElementIndex(index); return node(index).item; } Node<E> node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } } 2)迭代器遍历Iterator 对于RandomAccess类型的集合来说,如ArrayList迭代器遍历反而因为一些额外的操作,还会增加额外的运行时间; 对于Sequential Access的集合来说,因为Iterator内部维护了当前遍历的位置,所以每次遍历,读取下一个位置并不需要从集合的第一个元素开始查找,只要把指针向后移一位就行了,这样一来遍历整个集合的时间复杂度就降低为O(n);以LinkedList的迭代器为例,其内部实现,就是维护当前遍历的位置,然后操作指针移动就可以了 3)foreach循环遍历 分析Java字节码可知,foreach内部实现原理是通过Iterator实现的,只不过这个Iterator是Java编译器帮我们生成的,所以我们不需要再手动去编写。但是因为每次都要做类型转换检查,所以花费的时间比Iterator略长,而时间复杂度和Iterator是一样 ### 使用场景 ### 1)传统的for循环遍历基于计数器 适用于遍历顺序存储集合,读取性能比较高如ArrayList;不适用于遍历链式存储的集合如LinkedList,时间复杂度太大; 2)迭代器遍历Iterator 对于顺序存储的数据结构,如果不是太在意时间,推荐选择此方式,毕竟代码更加简洁,也防止了Off-By-One的问题。 链式存储:推荐此种遍历方式,平均时间复杂度降为O(n) 3)foreach循环遍历 foreach让代码更加简洁,缺点就是遍历过程中不能操作数据集合(删除等),所以有些场合不使用。而且它本身就是基于Iterator实现的,但是由于类型转换的问题,所以会比直接使用Iterator慢一点,性能上相差不大
相关 Java中集合类遍历问题实例 在Java中,当我们需要遍历集合中的元素时,会遇到几种常见的遍历方式。这里以ArrayList为例,给出几个实际的实例。 1. **for-each循环遍历:** ```ja 你的名字/ 2024年09月16日 20:39/ 0 赞/ 7 阅读
相关 Java集合遍历性能优化:实例对比 在Java编程中,对于集合的遍历操作,确实存在性能优化的空间。这里我们将通过几个具体的实例来展示优化的方法。 1. **List遍历**: - **原生循环**:`fo 太过爱你忘了你带给我的痛/ 2024年09月16日 13:42/ 0 赞/ 9 阅读
相关 Java集合框架遍历及性能优化案例 在Java编程中,集合框架如List、Set和Map是常用的数据存储结构。遍历这些集合以访问其元素时,可能面临性能问题。下面我们将通过几个实例来探讨这个问题以及如何优化。 1 小咪咪/ 2024年09月16日 00:36/ 0 赞/ 22 阅读
相关 Java中集合类遍历问题实例 在Java中,集合类如List、Set等的遍历主要是通过迭代器(Iterator)进行的。下面以List为例提供一个实例: ```java import java.util. Dear 丶/ 2024年09月13日 10:42/ 0 赞/ 17 阅读
相关 Java集合框架:遍历与性能优化问题 在Java的集合框架中,遍历是处理数据的主要方式。但是,有时候遍历过程中可能会遇到性能优化的问题。 1. **使用迭代器**:Java集合(如List、Set等)提供了迭代器 阳光穿透心脏的1/2处/ 2024年09月12日 13:18/ 0 赞/ 19 阅读
相关 详解Java中集合类的遍历方式 在Java中,集合类(如List、Set等)的遍历方式主要有两种:迭代器遍历和增强for循环遍历。 1. 迭代器遍历: ```java // 创建一个ArrayList实例 末蓝、/ 2024年09月11日 05:33/ 0 赞/ 16 阅读
相关 Java遍历集合 Java遍历集合 list,set,map 1.java遍历list public static void main(String[] args) { Dear 丶/ 2022年12月29日 02:17/ 0 赞/ 189 阅读
相关 Java中集合类遍历性能 集合元素在内存如何存放 数据元素在内存中,主要有2种存储方式: 1、顺序存储,Random Access(或直接存储,Direct Access): 这种方式,相 系统管理员/ 2022年05月09日 01:50/ 0 赞/ 119 阅读
相关 Java集合类系列(3)--遍历集合 简单遍历 使用System.out的println()方法 使用System.out的println()方法来输出集合对象时,将输出\[ele1,ele2,... 太过爱你忘了你带给我的痛/ 2021年09月14日 04:16/ 0 赞/ 342 阅读
还没有评论,来说两句吧...