美文网首页
Java基础HashMap简单改造

Java基础HashMap简单改造

作者: Imp_note | 来源:发表于2018-03-20 02:27 被阅读0次

    最近工作中遇到某些特定的需求,创建一个路由表Map,当把一堆路由信息key-value塞到一个HashMap,并加载到jvm中。同时逻辑代码中有大量的操作,需要去遍历这个Map。传统的HashMap会随着HashMap的大小增大,效率变得越来越低。所以对HashMap做了一些小改造。
    原理很简单,在原有的HashMap前,增加一次hash,缩小遍历范围。
    适用于初始化一次,就不怎么更改,只读不常写的场景,像固定加载到jvm中的路由数据、配置等。
    Demo:

    //map数量
    int mapCount = 500;
    //遍历次数
    int iteratorTimes = 1000000;
    //定义变种HashMap hash槽
    int hashCao = 10;
    Random random = new Random();
    //原有的HashMap 初始化 500个key-value
    Map<String, String> normalMap = new HashMap<>();
    for (int i = 0; i < mapCount; i++) {
        normalMap.put(String.valueOf(i), "我是" + String.valueOf(i));
    }
    //记录开始时间 遍历指定次数
    long startTime = System.currentTimeMillis();
    for (int x =0;x<iteratorTimes;x++) {
        String randomNum = String.valueOf(random.nextInt(mapCount));
        //System.out.println("随机数为:" + randomNum);
        for (Iterator<Map.Entry<String, String>> iterator = normalMap.entrySet().iterator(); iterator.hasNext(); ) {
            Map.Entry<String, String> entry = iterator.next();
            //模拟命中
            if (randomNum.equals(entry.getKey())) {
                //打印命中key-value
                //System.out.println("第" + entry.getKey() + "个:" + entry.getValue());
            }
        }
    }
    //普通HashMap结束
    long endTime = System.currentTimeMillis();
    //构造变种HashMap 外层map的key为自定义hash槽
    Map<Integer, Map<String,String>> fasterMap = new HashMap<>();
    //定义指定数量hash槽
    for (int j = 0; j < hashCao; j++) {
        fasterMap.put(j, new HashMap<>());
    }
    //按取模方式模拟 取出相应槽位的HashMap,再将数据塞入。
    for (int i = 0; i < mapCount; i++) {
        fasterMap.get(i % hashCao).put(String.valueOf(i), "我是" + String.valueOf(i));
    }
    //记录变种HashMap 遍历开始时间
    long startTime2 = System.currentTimeMillis();
    //遍历指定次数
    for (int x = 0; x < iteratorTimes; x++) {
        int randInt = random.nextInt(mapCount);
        //每次遍历 用随机数按hash槽数取模来模拟,取出相应槽位hashMap
        Map<String, String> curMap = fasterMap.get(randInt % hashCao);
        String randomNum = String.valueOf(randInt);
        //打印生成的随机数
        //System.out.println("随机数为:" + randomNum);
        //遍历相应槽位HashMap
        for (Iterator<Map.Entry<String, String>> iterator = curMap.entrySet().iterator(); iterator.hasNext(); ) {
            Map.Entry<String, String> entry = iterator.next();
            if (randomNum.equals(entry.getKey())) {
                //模拟命中
                //System.out.println("第" + entry.getKey() + "个:" + entry.getValue());
            }
        }
    }
    //变种HashMap结束
    long endTime2 = System.currentTimeMillis();
    System.out.println("normalMap耗时:" + (endTime - startTime));
    System.out.println("fasterMap耗时:" + (endTime2 - startTime2));
    

    给出几组数据结果(每种情况由于Random随机数的不稳定因素,每次结果可能会不一样,但不影响大致趋势)

    map中key-value数量/个 hash槽数/个 遍历次数/次 普通hashMap耗时/ms 变种fasterMap 耗时/ms
    5 10 1000,000 296 224
    10 10 1000,000 248 240
    100 10 1000,000 1410 206
    100 100 1000,000 1425 257
    500 10 1000,000 4634 519
    500 100 1000,000 4107 177
    1000 10 1000,000 7872 866
    1000 100 1000,000 7832 141

    相对来说,是一种空间换时间的做法,特定场景下还算可观,文中取模的步骤可以根据需求替换成hash等等一些算法。

    相关文章

      网友评论

          本文标题:Java基础HashMap简单改造

          本文链接:https://www.haomeiwen.com/subject/vuomqftx.html