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. ebook 电子书项目

    ebook电子书网站使用eclipse开发,开发语言主体是JAVA,使用的是servlet+jsp,前端使用javascript和jQuery,页面布局设计使用的是bootstrap,在这里我记下我开 ...

  2. java运算符二

    一 赋值运算符 /* * 赋值运算符 * +=, -=, *=, /=, %= : * 上面的运算符作用:将等号左右两边计算,会将结果自动强转成等号左边的数据类型,再赋值给等号左边的 * 注意:赋值运 ...

  3. C#LeetCode刷题之#788-旋转数字(Rotated Digits)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3967 访问. 我们称一个数 X 为好数, 如果它的每位数字逐个地 ...

  4. Deep Learning-Based Document Modeling for Personality Detection from Text 阅读笔记

    文章目录 代码地址 1. 摘要 2. 方法综述 2.1 输入信息预处理 2.2 文档层面的格式特征提取 2.3 数据过滤 2.4 单词层面上的特征提取 2.5分类 3. 分类网络结构 3.1 步骤 3 ...

  5. android studio实现圆角的button

    操作过程 1. 在drawable中新建一个button_circle_shape.xml 但是建立这个xml是有操作的,因为从drawable右键是创建不了xml的, 具体操作如下: 右键res–& ...

  6. [Hei-Ocelot-Gateway ].Net Core Api网关Ocelot的开箱即用版本

    写在前面 很多neter都有在用Ocelot做Api网关,但是Ocelot又不像kong或者其他网关一样,开箱即用.它需要你单独开一个web项目来部署,这样很多同学都在做重复的事了. 这里[Hei.O ...

  7. MySQL是如何实现事务的ACID

    前言 最近在面试,有被问到,MySQL的InnoDB引擎是如何实现事务的,又或者说是如何实现ACID这几个特性的,当时没有答好,所以自己总结出来,记录一下. 事务的四大特性ACID 事务的四大特性AC ...

  8. 细讲前端设置cookie, 储存用户登录信息

    细讲前端设置cookie 引言 正文 一.设置cookie 二.查看cookie 三.删除cookie 四.封装cookie操作 结束语 引言 我们都知道如果想做一个用户登录并使浏览器保存其登录信息, ...

  9. Python 源代码代码打包成 whl 文件

    1.检查 python setup.py check 2.打包 python setup.py sdist bdist_wheel || true

  10. 吊打 Tomcat ,Undertow 性能很炸!!

    在 Java Web 容器的世界里,Tomcat 和 Jetty 是大名鼎鼎的.用的最多的开源项目,也是大众熟知的. 今天再介绍另外一款能和 Tomcat 媲美的神器:Undertow,据说性能方面还 ...