Java数据存储类型ArrayList、HashSet、HashMap、LinkedList使用不同遍历方法效率研究By Python

2023-11-03

Java不同数据存储类型使用不同遍历方法效率研究

GitHub代码仓库

数据存储类型

  • ArrayList
  • HashSet
  • HashMap
  • LinkedList

遍历方法

  • 传统遍历方法
for(int i=0;i<list.size();i++) {
   String str = list.get(i);
   ...
}
  • 内置迭代器
for (String str : list) {
   ...
}
  • 显式迭代器
Iterator<String> it = list.iterator();
while(it.hasNext()) {
  String str = it.next();
  ...
}

测试代码模板

  • 使用大小为 N N N的数组,遍历 M M M边,平均遍历速度定义为 T / ( N ∗ M ) T/(N*M) T/(NM)
    private static ArrayList<String> list = new ArrayList<>();
    private final static int N = 1000000, M = 1000;
    private final static String STR = "abcdefg";
  • 首先建立一个固定数组,供给3个遍历方法使用
    @BeforeClass
    public static void CreateList() {
		for (int i = 0; i < N; i++) {
		    list.add(STR);
		}
    }

使用JUnit测试单元记录时间

  • 传统遍历方法For
    @Test
    public void FOR() {
		for (int k = 0; k < M; k++) {
		    for (int i = 0; i < list.size(); i++) {
			String str = list.get(i);
		    }
		}
    }
  • 内置迭代器
    @Test
    public void Inner_Iteration() {
		for (int k = 0; k < M; k++) {
		    for (String str : list) {
			String s = str;
		    }
		}
    }
  • 显式迭代器
    @Test
    public void Explicit_Iteration() {
		for (int k = 0; k < M; k++) {
		    Iterator<String> it = list.iterator();
		    while (it.hasNext()) {
			String str = it.next();
		    }
		}
    }

根据不同的存储类型进行更改
eg. HashMap 要设置key和value

Python数据可视化

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
%matplotlib inline
  • 以ArrayList代码为例
  • 柱状图
f, ax= plt.subplots()
ArrayList = pd.read_csv("../csv/ArrayList.csv")
sns.barplot(data=ArrayList)
ax.set_title("ArrayList")
  • 折线图
f, ax= plt.subplots()
sns.lineplot(data=ArrayList)
ax.set_title("ArrayList")
plt.ylim(0.5, 1.0)

ArrayList

  • 整体来说,在ArrayList中for的遍历速度最快内置迭代器和显式迭代器相当
  • 并且ArrayList迭代非常稳定,尤其是for
Explicit_Iteration FOR Inner_Iteration
0.775 0.585 0.757
0.785 0.577 0.748
0.783 0.581 0.769
0.775 0.583 0.77
0.778 0.602 0.788
0.784 0.586 0.767
0.775 0.581 0.807
0.814 0.587 0.766
0.786 0.604 0.839
0.815 0.593 0.775


HashMap

  • 在HashMap中不能使用For,内置迭代器略优
Explicit_Iteration Inner_Iteration
0.608 0.507
0.622 0.613
0.585 0.485
0.587 0.533
0.639 0.526
0.593 0.555
0.534 0.431
0.581 0.504
0.598 0.481
0.64 0.504


HashSet

  • 在HashSet中同样不能使用for, 基本相同,内置迭代器较不稳定
Explicit_Iteration Inner_Iteration
2.5 2.517
2.532 2.477
2.684 2.523
2.697 3.303
2.631 2.515
2.956 3.016
3.281 3.051
3.074 2.95
3.206 2.935
2.89 2.887


LinkedList

  • 注:在链表中可以使用for,但是根据一定的测试,随着数据规模增加,运行时间呈指数型增长,与另两种遍历方法不在一个数量级上,所以不加入统计。

  • 在LinkedList中,内置迭代器和显式迭代器效率相当,多个单次试验观察来说显式迭代器略优
Explicit_Iteration Inner_Iteration
1.865 2.101
1.883 1.929
1.9 1.941
1.843 1.903
1.89 1.897
1.835 1.921
1.841 1.846
1.914 1.902
1.872 1.859
1.816 1.827


数据处理和数据清洗

  • 将4中存储类型的数据整合起来
  • 将数据统一到同样的数据尺度
Base = 0

ArrayList /= 10**(Base-8)
ArrayList['Type'] = 'ArrayList'     # 8

HashMap /= 10**(Base-7)
HashMap['Type'] = 'HashMap'         # 7

HashSet /= 10**(Base-8)
HashSet['Type'] = 'HashSet'         # 8

LinkedList /= 10**(Base-8)
LinkedList['Type'] = 'LinkedList'  # 8
  • 由于不同数据类型效率差异较大
  • 作者选择通过取对数 l o g 10 ( ) log_{10}() log10()的方法
  • 然后取相反数(时间越少,效率越高)
  • 这使数据数量级接近,能容易可视化
data = pd.concat([ArrayList, HashMap, HashSet, LinkedList], ignore_index=True).drop(['FOR'], axis=1)
data[['Explicit_Iteration', 'Inner_Iteration']] = np.log10(data[['Explicit_Iteration', 'Inner_Iteration']])

整体可视化对比

  • 将内置迭代器、显式迭代器分别处理后数据对比
  • 下图的数据表示效率相对值的数量级
f, ax= plt.subplots()
sns.barplot(x='Type', y='Inner_Iteration', data=data)
ax.set_title("Inner_Iteration")

f, ax= plt.subplots()
sns.barplot(x='Type', y='Explicit_Iteration', data=data)
ax.set_title("Explicit_Iteration")

分析

本质:数组、集合、字典、链表,4种数据结构的差异在遍历方式上的体现

ArrayList

  • ArrayList本质上是一个动态数组,数组对于大量随机访问有着高效的响应速度
  • 迭代器在ArrayList这种不依赖__iter____next__方法的对象,在使用迭代器时的访存速度远不如有序访存FOR
  • 由于数组线性存储,导致ArrayList增加和删除操作效率较低
  • 因此ArrayList适用于不定长、不频繁增删的数据存储

HashMap

  • Java种的Map主要分为HashMap和TreeMap,属于非Collection接口
  • Map需要有键key和值value,内部元素无序,因此无法用For访问
  • 使用迭代器时,由于键值的唯一性,单个元素查找速度似乎较快
  • 但迭代对象时键值的集合,keySet()的迭代需要占用时间
  • 而且键值是无序的,一定程度上,不满足良好局部性的要求

HashSet

  • HashSet继承了Collection种的Set
  • HashSet调用了HashMap.put()方法,将值直接作为键
  • 所以HashSet在访问时一定优于HashMap,因为Set不需要对Keys的迭代
  • 事实证明,HashSet确实远优于HashMap,但从实用性角度来说却不如HashMap

LinkedList

  • LinkedList本质上是一个双向链表
  • 链表的特点就是容易增加和删除,但随机访问单个元素效率很低

总结

  • 不同的4种数据存储类型中3种迭代方式效率不同
  • 内置迭代器和显式迭代器效率相当,for在ArrayList中效率较高、LinkedList很差
  • HashSet的迭代效率较高,HashMap迭代效率较低
  • 单从迭代器迭代速度来说:HashSet > LinkedList > ArrayList > HashMap
  • 总体评价:
    • ArrayList:少增删,求稳定
    • HashMap:字典功能,效率低
    • HashSet:大数据非数字随机元素查找极快
    • LinkedList:增删高速,严禁用for
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java数据存储类型ArrayList、HashSet、HashMap、LinkedList使用不同遍历方法效率研究By Python 的相关文章

随机推荐

  • ModbusSlave安装及使用指南正式版带序列码

    ModbusSlave是一个从站设备仿真软件 它用于接收主设备的命令包 并回送数据包 可用于测试和调试Modbus主站设备 便于观察Modbus通信过程中的各种报文 ModbusSlave支持ModbusRTU ASCII TCP IP等协
  • 基于Xposed hook 实时监测微信消息的三种策略

    本文以微信版本6 7 3为例进行分析有hook 大部分做微信机器人的话 首先要实时抓取微信的消息 在这里展示三种方式对微信的消息进行hook 1 基于UI层拉取加载进行监听 2 基于微信dao层调用的保存进行监听 3 基于数据库的插入保存进
  • 决策树 prepruning_数据挖掘入门系列教程(三点五)之决策树

    本来还是想像以前一样 继续学习 Python数据挖掘入门与实践 的第三章 决策树 但是这本书上来就直接给我怼了一大串代码 对于决策树基本上没有什么介绍 可直接把我给弄懵逼了 主要我只听过决策树还没有认真的了解过它 这一章节主要是对决策树做一
  • SD方法

    4 4 SD方法 结构化的设计方法 数据流图 gt 软件结构图 描述软件的结构图 层次图 结构图 SD方法 DFD gt 软件结构图 1 DFD图的类型 变换型 为核心处理准备数据 输入数据流 核心处理 变换中心 对核心处理的结果作出处理
  • CAP和BASE理论

    CAP理论 CAP是 Consistency Availability Partition tolerance 三个词语的缩写 分别表示一致性 可用性 分区容忍性 它指出一个分布式计算系统不可能同时满足以下三点 一致性 Consistenc
  • 小白学PYTHON时最容易犯的6个错误,看看你遇到过几个

    最近又在跟之前的同学一起学习python 一起进步 发现很多测试同学在初学python的时候很容易犯一些错误 特意总结了一下 其实这些错误不仅是在学python时会碰到 在学习其他语言的时候也同样会碰到 错误1 缩进 python是强制缩进
  • GET 和 POST的区别? 用POST方法发送登陆请求

    GET 和 POST的区别 用POST方法发送登陆请求 lt 1 gt http方法 http协议定义了很多方法对应不同的资源操作 其中最常用的是GET 和 POST 方法 GET POST OPTIONS HEAD PUT DELETE
  • 什么是计算机网络中的127.0.0.1 IP地址或Localhost?

    IP addresses are used to specify the hosts in a numeric way There are different types of IP addresses in Computer networ
  • 听说渲影很便宜,是真的吗?

    这次我比较了3个平台 炫云 渲影和渲染100 首先说结论 渲影是很便宜 但也没便宜过渲染100 而且出图大小有猫腻 具体的往下看 首先我选取了一个219M的场景 不是很大 设置的分辨率是3200 4000 提交3个平台的时候选择的参数也一样
  • 《C++标准库》学习笔记 — STL — 并发 — 线程同步与并发 — mutex 与 lock

    C 标准库 学习笔记 STL 并发 线程同步与并发 mutex 与 lock 一 线程同步与并发并发问题 1 出错情况 1 未同步化的数据访问 2 写至半途的数据 3 重新安排的语句 2 解决问题需要的特性 3 C 并发的支持 二 Mute
  • C#中仿QQ截图

    欢迎大家提出意见 一起讨论 转载请标明是引用于 http blog csdn net chenyujing1234 代码 VS2008 http www rayfile com zh cn files bad4b357 978a 11e1
  • cmake使用教程(七)-流程和循环

    cmake系列使用教程 cmake使用教程 一 起步 cmake使用教程 二 添加库 cmake使用教程 三 安装 测试 系统自检 cmake使用教程 四 文件生成器 cmake使用教程 五 cpack生成安装包 cmake使用教程 六 蛋
  • TVS管原理和特性

    介绍TVS管的资料太多 中文的也有非常多 不过大多数的都是翻译的 在文章最后有所有文件的目录和下载 这里主要介绍原理特性和参数 然后画一些时间分析一下散热选取 最后把PCB总结一下 瞬态二极管 TVS Transient Voltage S
  • JavaWeb实现记住密码功能(使用Cookie)

    JavaWeb实现记住密码功能 使用Cookie 1 Cookie知识点 cookie介绍 背景 HTTP协议作是 状态协议 状态指每次request请求之前是相互独 的 当前请求 并不会记录它的上 次请求信息 存在这样的问题 既然 状态
  • 内联函数

    引入内联函数的目的是为了解决程序中函数调用的效率问题 函数是一种更高级的抽象 它的引入使得编程者只关心函数的功能和使用方法 而不必关心函数功能的具体实现 函数的引入可以减少程序的目标代码 实现程序代码和数据的共享 但是 函数调用也会带来降低
  • 【实践经验】cp 错误:cannot create regular file ‘../../src/ood1.jpg‘: No such file or directory

    今日在linux拷贝文件的时候 出现这个错误感觉很奇怪 命名目标目录是存在的 但是为什么会报错呢 其实出现这个问题的原因是 你所看到的目录结构可能不是真正的目录结构 比如我在拷贝的时候执行的命令是 cp 806252c538fffb0948
  • uniapp App调试及更新

    uniapp App专题 本章主要对App的调试方式 虚拟机 物理机 安装及更新方面进行总结 连接设备进行调试 准备工作 首先需要打开设备的开发者模式 设置中找到版本号 连续点击版本号直到出现提示 您现在已处于开发者模式 点击进入开发者选项
  • CocosCreator中的Prefab文件格式总结

    CocosCreator所有的Prefab都是以下类似的格式 我们学会用文本编辑器查看Prefab文件 可以帮助我们更轻松的查找节点 查看节点和组件信息 批量修改节点和组件信息等等 因为在文本编辑器中的Prefab文件才是原始的 而且Coc
  • 【clion】实现类似自定义代码自动补全的功能(懒人利器)

    比如我有句代码是经常要使用的 如下 freopen Users zhangkanqi Desktop 11 txt r stdin 但是自动补全里并没有这句话 网上也没有找到如何自定义自动补全的语句 学艺不精 可是我每次又懒得写这句话 因为
  • Java数据存储类型ArrayList、HashSet、HashMap、LinkedList使用不同遍历方法效率研究By Python

    Java不同数据存储类型使用不同遍历方法效率研究 GitHub代码仓库 数据存储类型 ArrayList HashSet HashMap LinkedList 遍历方法 传统遍历方法 for int i 0 i