• [Java数据结构]Map的contiansKey和List的contains比较


    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

  • 相关阅读:
    【SCOI2012】滑雪
    【NOI2008】假面舞会
    ※初赛知识总结※
    【FJSC2012】足球
    【中山市选2011】杀人游戏
    【SDOI2008】洞穴勘测
    【SNOI2017】炸弹
    【LGOJ1606】白银莲花池
    int类型中为什么负数比正数多了一个数?
    utf8、utf16、utf32之间的格式
  • 原文地址:https://www.cnblogs.com/heyang78/p/12095121.html
Copyright © 2020-2023  润新知