Map的containskey方法使用哈希算法查找key是否存在,运算时间是常数;

List的contains方法是将元素在列表中遍历,运算时间和列表长度有关。

我使用两种不同SQL语句获取两种不同类型的结果集进行比较,发现两者差别很明显。

名称 类型 比较方法 耗时
两个含35,7282数据的map对比 map containsKey 101ms
两个含36,13962数据的list对比 list contains 46s455ms

至于Map包含的数据量略少于map,是因为存在重复key,map把它过滤掉了,这在结果集比较时有一小段是缺乏证明的,需要用另外的手段再验证。

代码:

package com.ufo.leftjoin;

import java.security.MessageDigest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties; import org.apache.log4j.Logger; public class SqlComparator {
private static Logger log = Logger.getLogger(SqlComparator.class); public void compare() {
Connection conn = null;
Statement stmt = null; try {
Class.forName(DBParam.Driver).newInstance();
Properties pro = new Properties();
pro.setProperty("user", DBParam.User);
pro.setProperty("password", DBParam.Pswd); conn = DriverManager.getConnection(DBParam.DbUrl, pro);
stmt = conn.createStatement(); //compareUsingMap(stmt); compareUsingList(stmt);
} catch (Exception e) {
System.out.print(e.getMessage());
e.printStackTrace();
} finally {
try {
stmt.close();
conn.close();
} catch (SQLException e) {
log.error("Can't close stmt/conn because of " + e.getMessage());
}
}
} private void compareUsingMap(Statement stmt) throws SQLException {
long startMs = System.currentTimeMillis();
Map<String,DhItem> leftMap=getMapFrom(getLeftjoinSql(),stmt);
long endMs = System.currentTimeMillis();
log.info("It takes "+ms2DHMS(startMs,endMs)+" to get leftMap.");
int leftCount=leftMap.size();
log.info("There are "+toEastNumFormat(leftCount)+" records in leftMap."); startMs = System.currentTimeMillis();
Map<String,DhItem> notexistMap=getMapFrom(getNotExistSql(),stmt);
endMs = System.currentTimeMillis();
log.info("It takes "+ms2DHMS(startMs,endMs)+" to get notexistMap.");
int notexistCount=notexistMap.size();
log.info("There are "+toEastNumFormat(notexistCount)+" records in notexistMap."); startMs = System.currentTimeMillis();
List<DhItem> onlyInInnerLs=new ArrayList<DhItem>();
int count=0;
for(String key:notexistMap.keySet()) {
if(leftMap.containsKey(key)) {
count++;
}else {
DhItem dhItem=notexistMap.get(key);
onlyInInnerLs.add(dhItem);
}
} log.info("There are "+toEastNumFormat(count)+" records in two maps.");
log.info("There are "+toEastNumFormat(onlyInInnerLs.size())+" records only in notexistMap.");
endMs = System.currentTimeMillis();
log.info("It takes "+ms2DHMS(startMs,endMs)+" to complete comparison using map.");
} private void compareUsingList(Statement stmt) throws SQLException {
long startMs = System.currentTimeMillis();
List<DhItem> leftList=getListFrom(getLeftjoinSql(),stmt);
long endMs = System.currentTimeMillis();
log.info("It takes "+ms2DHMS(startMs,endMs)+" to get leftList.");
int leftCount=leftList.size();
log.info("There are "+toEastNumFormat(leftCount)+" records in leftList."); startMs = System.currentTimeMillis();
List<DhItem> notexistList=getListFrom(getNotExistSql(),stmt);
endMs = System.currentTimeMillis();
log.info("It takes "+ms2DHMS(startMs,endMs)+" to get notexistList.");
int notexistCount=notexistList.size();
log.info("There are "+toEastNumFormat(notexistCount)+" records in notexistList."); startMs = System.currentTimeMillis();
List<DhItem> onlyInInnerLs=new ArrayList<DhItem>();
int count=0;
for(DhItem item:notexistList) {
if(leftList.contains(item)) {
count++;
}else {
onlyInInnerLs.add(item);
}
} log.info("There are "+toEastNumFormat(count)+" records in two lists.");
log.info("There are "+toEastNumFormat(onlyInInnerLs.size())+" records only in notexistList.");
endMs = System.currentTimeMillis();
log.info("It takes "+ms2DHMS(startMs,endMs)+" to complete comparison using list.");
} private List<DhItem> getListFrom(String sql,Statement stmt) throws SQLException {
List<DhItem> list=new ArrayList<DhItem>(); ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
DhItem dhItem=new DhItem();
dhItem.order_no=rs.getString("order_no");
dhItem.shipper_code=rs.getString("shipper_code");
dhItem.vehicle_name=rs.getString("vehicle_name");
dhItem.vehicle_code=rs.getString("vehicle_code");
dhItem.reason_name_mobile=rs.getString("reason_name_mobile");
dhItem.status_name_mobile=rs.getString("status_name_mobile");
list.add(dhItem);
} return list;
} private Map<String,DhItem> getMapFrom(String sql,Statement stmt) throws SQLException {
Map<String,DhItem> map=new HashMap<String,DhItem>(); ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
DhItem dhItem=new DhItem();
dhItem.order_no=rs.getString("order_no");
dhItem.shipper_code=rs.getString("shipper_code");
dhItem.vehicle_name=rs.getString("vehicle_name");
dhItem.vehicle_code=rs.getString("vehicle_code");
dhItem.reason_name_mobile=rs.getString("reason_name_mobile");
dhItem.status_name_mobile=rs.getString("status_name_mobile");
map.put(toMD5(dhItem.toString()), dhItem);
} return map;
} private String getLeftjoinSql() {
StringBuilder sb = new StringBuilder();
sb.append(" SELECT ");
sb.append(" DH1.ORDER_NO, ");
sb.append(" DH1.SHIPPER_CODE , ");
sb.append(" DH1.VEHICLE_NAME, ");
sb.append(" DH1.VEHICLE_CODE , ");
sb.append(" DH1.REASON_NAME_MOBILE, ");
sb.append(" DH1.STATUS_NAME_MOBILE ");
sb.append(" from ");
sb.append(" DELIVERY_HISTORY DH1 ");
sb.append(" left JOIN DELIVERY_HISTORY DH2 on ");
sb.append(" DH1.SHIPPER_CODE = DH2.SHIPPER_CODE ");
sb.append(" and DH1.ORDER_NO = DH2.ORDER_NO ");
sb.append(" and DH2.UPDATED_DATETIME > DH1.UPDATED_DATETIME ");
sb.append(" where DH2.UPDATED_DATETIME IS NULL ");
sb.append(" and DH1.DISABLED_FLG = 0 ");
String sql = sb.toString();
return sql;
} private String getInnerSql() {
StringBuilder sb = new StringBuilder();
sb.append(" select ");
sb.append(" DH1.ORDER_NO, ");
sb.append(" DH1.SHIPPER_CODE , ");
sb.append(" DH1.VEHICLE_NAME, ");
sb.append(" DH1.VEHICLE_CODE , ");
sb.append(" DH1.REASON_NAME_MOBILE, ");
sb.append(" DH1.STATUS_NAME_MOBILE ");
sb.append(" from ");
sb.append(" DELIVERY_HISTORY dh1 , ");
sb.append(" (select SHIPPER_CODE,ORDER_NO,max(UPDATED_DATETIME) as utime from DELIVERY_HISTORY ");
sb.append(" group by SHIPPER_CODE,ORDER_NO) dh2 ");
sb.append(" where ");
sb.append(" dh1.SHIPPER_CODE=dh2.SHIPPER_CODE and ");
sb.append(" dh1.ORDER_NO=dh2.ORDER_NO and ");
sb.append(" dh1.UPDATED_DATETIME=dh2.utime and ");
sb.append(" dh1.DISABLED_FLG='0' "); String sql = sb.toString(); return sql;
} private String getNotExistSql() {
StringBuilder sb = new StringBuilder();
sb.append(" select ");
sb.append(" a.ORDER_NO, ");
sb.append(" a.SHIPPER_CODE , ");
sb.append(" a.VEHICLE_NAME, ");
sb.append(" a.VEHICLE_CODE , ");
sb.append(" a.REASON_NAME_MOBILE, ");
sb.append(" a.STATUS_NAME_MOBILE ,");
sb.append(" a.UPDATED_DATETIME");
sb.append(" from DELIVERY_HISTORY a");
sb.append(" where not exists(select 1 ");
sb.append(" from DELIVERY_HISTORY b");
sb.append(" where b.SHIPPER_CODE=a.SHIPPER_CODE and b.ORDER_NO=a.ORDER_NO and b.UPDATED_DATETIME>a.UPDATED_DATETIME)");
sb.append(" and a.DISABLED_FLG=0 "); String sql = sb.toString();
return sql;
} // 将整数在万分位以逗号分隔表示
public static String toEastNumFormat(long number) {
DecimalFormat df = new DecimalFormat("#,####");
return df.format(number);
} /**
* change seconds to DayHourMinuteSecond format
*
* @param startMs
* @param endMs
* @return
*/
private static String ms2DHMS(long startMs, long endMs) {
String retval = null;
long secondCount = (endMs - startMs) / 1000;
String ms = (endMs - startMs) % 1000 + "ms"; long days = secondCount / (60 * 60 * 24);
long hours = (secondCount % (60 * 60 * 24)) / (60 * 60);
long minutes = (secondCount % (60 * 60)) / 60;
long seconds = secondCount % 60; if (days > 0) {
retval = days + "d" + hours + "h" + minutes + "m" + seconds + "s";
} else if (hours > 0) {
retval = hours + "h" + minutes + "m" + seconds + "s";
} else if (minutes > 0) {
retval = minutes + "m" + seconds + "s";
} else {
retval = seconds + "s";
} return retval + ms;
} public static String toMD5(String key) {
char hexDigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
try {
byte[] btInput = key.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
return null;
}
} public static void main(String[] args) {
SqlComparator sc=new SqlComparator();
sc.compare();
}
}

输出:

2019-12-25 10:31:17,997  INFO [main] - It takes 2m36s81ms to get leftMap.
2019-12-25 10:31:18,002 INFO [main] - There are 35,7282 records in leftMap.
2019-12-25 10:33:57,147 INFO [main] - It takes 2m39s145ms to get notexistMap.
2019-12-25 10:33:57,147 INFO [main] - There are 35,7282 records in notexistMap.
2019-12-25 10:33:57,247 INFO [main] - There are 35,7282 records in two maps.
2019-12-25 10:33:57,247 INFO [main] - There are 0 records only in notexistMap.
2019-12-25 10:33:57,248 INFO [main] - It takes 0s101ms to complete comparison using map. 2019-12-25 10:44:22,695 INFO [main] - It takes 2m36s52ms to get leftList.
2019-12-25 10:44:22,700 INFO [main] - There are 36,1396 records in leftList.
2019-12-25 10:46:55,335 INFO [main] - It takes 2m32s634ms to get notexistList.
2019-12-25 10:46:55,335 INFO [main] - There are 36,1396 records in notexistList.
2019-12-25 10:47:41,789 INFO [main] - There are 0 records in two lists.
2019-12-25 10:47:41,790 INFO [main] - There are 36,1396 records only in notexistList.
2019-12-25 10:47:41,790 INFO [main] - It takes 46s455ms to complete comparison using list.

--END-- 2019-12-25 11:45

[Java数据结构]Map的contiansKey和List的contains比较的更多相关文章

  1. Java数据结构-------Map

    常用Map:Hashtable.HashMap.LinkedHashMap.TreeMap 类继承关系: HashMap 1)无序:  2)访问速度快:  3)key不允许重复(只允许存在一个null ...

  2. Java中常见数据结构Map之LinkedHashMap

    前面已经说完了HashMap, 接着来说下LinkedHashMap. 看到Linked就知道它是有序的Map,即插入顺序和取出顺序是一致的, 究竟是怎样做到的呢? 下面就一窥源码吧. 1, Link ...

  3. (7)Java数据结构--集合map,set,list详解

    MAP,SET,LIST,等JAVA中集合解析(了解) - clam_clam的专栏 - CSDN博---有颜色, http://blog.csdn.net/clam_clam/article/det ...

  4. Java遍历Map的3种方式

    package test; import java.util.Collection; import java.util.HashMap; import java.util.Map; import ja ...

  5. Java API —— Map接口

    1.Map接口概述         · 将键映射到值的对象         · 一个映射不能包含重复的键         · 每个键最多只能映射到一个值   2.Map接口和Collection接口的 ...

  6. Java中间Map List Set和其他收藏品

    Map List Set和其他收藏品: 一.概述 在JAVA的util包中有两个全部集合的父接口Collection和Map,它们的父子关系: +Collection 这个接口extends自 --j ...

  7. Java实现Map集合二级联动

    Map集合可以保存键值映射关系,这非常适合本实例所需要的数据结构,所有省份信息可以保存为Map集合的键,而每个键可以保存对应的城市信息,本实例就是利用Map集合实现了省市级联选择框,当选择省份信息时, ...

  8. (6)Java数据结构-- 转:JAVA常用数据结构及原理分析

    JAVA常用数据结构及原理分析  http://www.2cto.com/kf/201506/412305.html 前不久面试官让我说一下怎么理解java数据结构框架,之前也看过部分源码,balab ...

  9. (2)Java数据结构--二叉树 -和排序算法实现

    === 注释:此人博客对很多个数据结构类都有讲解-并加以实例 Java API —— ArrayList类 & Vector类 & LinkList类Java API —— BigDe ...

随机推荐

  1. git使用-git仓库

    1.初始化版本库 git init 2.添加文件到版本库 git add git commit 3.查看仓库状态 git status 4.撤销初始化命令 rm -rf .git

  2. Mybatis——ResultMap(结果集映射)的使用

    ResultMap的使用 在Mybatis中,可以使用resultMap(结果集映射)作为sql的返回类型 一般用来解决如下问题: 数据库表字段名和实体类属性名不一致的问题: 多对一问题: 例如:多个 ...

  3. 极简 Node.js 入门 - 3.1 File System API 风格

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  4. 简单快速搭建钓鱼wifi

    前言 钓鱼wifi是很久的话题了,但是传统的方法可能比较麻烦需要手动配置dhcp,dns,网卡,流量转发,比较麻烦,而且还有根据每次的网络环境需要重新的配置,这里介绍用WIFIpumpkin3工具简单 ...

  5. Java中的策略模式,完成一个简单地购物车,两种付款策略实例教程

    策略模式是一种行为模式.用于某一个具体的项目有多个可供选择的算法策略,客户端在其运行时根据不同需求决定使用某一具体算法策略. 策略模式也被称作政策模式.实现过程为,首先定义不同的算法策略,然后客户端把 ...

  6. Python 函数为什么会默认返回 None?

    Python 有一项默认的做法,很多编程语言都没有--它的所有函数都会有一个返回值,不管你有没有写 return 语句. 本文出自"Python为什么"系列,在正式开始之前,我们就 ...

  7. 区分多个web driver实例

    固然可以用加载不同cookie的办法,让3个帐号共享一个web driver登陆,但总感觉切换麻烦,干脆用了3个web driver实例.问题来了,如何区分?不是说程序里如何区分,机器比人聪明,知道外 ...

  8. 如何校验内存数据的一致性,DynamicExpresso 算是帮上大忙了

    一:背景 1. 讲故事 记的在上一家公司做全内存项目的时候,因为一些关键表会在程序 startup 的时候全量灌入到内存中,但随着时间的推移,内存和数据库的同步偶尔会出现数据差异的情况,伴随着就是运营 ...

  9. 安国AU6989主控 + K9GBG08U0A(NAND) 制作4GB闪存驱动器

    文档标识符:AU6989_FLASH-DRIVE_D-P8 作者:DLHC 最后修改日期:2020.8.22 本文链接: https://www.cnblogs.com/DLHC-TECH/p/AU6 ...

  10. 10分钟搞定 Java 并发队列好吗?好的

    | 好看请赞,养成习惯 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it ...