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. MySQL回表查询

    一.MySQL索引类型 1.普通索引:最基本的索引,没有任何限制 2.唯一索引(unique index):索引列的值必须唯一,但是允许为空 3.主键索引:特殊的唯一索引,但是不允许为空,一般在建表的 ...

  2. Windows下制作软件安装包

    一.下载 首先,下载SetupFactory9.0.3.0Trial(下载链接:https://www.haolizi.net/example/view_65380.html) 下载好会有一个压缩包 ...

  3. java 的API及Object类

    一 Java的API Java 的API(API: Application(应用) Programming(程序) Interface(接口)) Java API就是JDK中提供给我们使用的类,这些类 ...

  4. 2020-03-27:分布式锁的问题,假如a线程在获得锁的情况下 网络波动 极端情况是断网了,这种情况是怎么处理的

    福哥答案2020-04-04:超时释放锁.

  5. Vue $nextTick的一个使用场景

    $nextTick 官方解释 在下次 DOM 更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法,获取更新后的 DOM 使用场景 在页面上有2个表单元素和2个按钮 btnRequiredFi ...

  6. Android 开发学习进程0.19 webview 的使用

    Android 中的webview android 中的webview是可以在app内部打开HTML等的网页,不必再打开浏览器,有两种实现方法,即webviewclient webChromeclie ...

  7. 每日一道 LeetCode (15):二进制求和

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

  8. Enumerable 下又有新的扩展方法啦,快来一起一睹为快吧

    一:背景 1. 讲故事 前段时间将公司的一个项目从 4.5 升级到了 framework 4.8 ,编码的时候发现 Enumerable 中多了三个扩展方法: Append, Prepend, ToH ...

  9. C++类和对象的封装 点和圆的案例

    主要练习 :在类中可以让另一个类作为本类的成员. 案例:判断点和圆的位置关系. 一.第一种直接方法 using namespace std; #include <iostream> cla ...

  10. Jmeter 常用函数(13)- 详解 __machineIP

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 返回机器(电脑)IP 语法格式 ${_ ...