zoukankan      html  css  js  c++  java
  • 集合框架系列教材 (十六)- 其他

    步骤1:List查找的低效率
    步骤2:HashMap的性能表现
    步骤3:HashMap原理与字典
    步骤4:分析HashMap性能卓越的原因
    步骤5:HashSet判断是否重复
    步骤6:练习-自定义字符串的hashcode
    步骤7:答案-自定义字符串的hashcode
    步骤8:练习-自定义MyHashMap
    步骤9:答案-自定义MyHashMap
    步骤10:练习-内容查找性能比较
    步骤11:答案-内容查找性能比较

    步骤 1 : List查找的低效率

    假设在List中存放着无重复名称,没有顺序的2000000个Hero
    要把名字叫做“hero 1000000”的对象找出来
    List的做法是对每一个进行挨个遍历,直到找到名字叫做“hero 1000000”的英雄。
    最差的情况下,需要遍历和比较2000000次,才能找到对应的英雄。
    测试逻辑:
    1. 初始化2000000个对象到ArrayList中
    2. 打乱容器中的数据顺序
    3. 进行10次查询,统计每一次消耗的时间
    不同计算机的配置情况下,所花的时间是有区别的。 在本机上,花掉的时间大概是600毫秒左右

    List查找的低效率

    package collection;

         

    import java.util.ArrayList;

    import java.util.Collections;

    import java.util.List;

         

    import charactor.Hero;

         

    public class TestCollection {

        public static void main(String[] args) {

            List<Hero> heros = new ArrayList<Hero>();

                

            for (int j = 0; j < 2000000; j++) {

                Hero h = new Hero("Hero " + j);

                heros.add(h);

            }

                

            // 进行10次查找,观察大体的平均值

            for (int i = 0; i < 10; i++) {

                // 打乱heros中元素的顺序

                Collections.shuffle(heros);

                 

                long start = System.currentTimeMillis();

         

                String target = "Hero 1000000";

         

                for (Hero hero : heros) {

                    if (hero.name.equals(target)) {

                        System.out.println("找到了 hero!" );

                        break;

                    }

                }

                long end = System.currentTimeMillis();

                long elapsed = end - start;

                System.out.println("一共花了:" + elapsed + " 毫秒");

            }

                 

        }

    }

    步骤 2 : HashMap的性能表现

    使用HashMap 做同样的查找
    1. 初始化2000000个对象到HashMap中。
    2. 进行10次查询
    3. 统计每一次的查询消耗的时间
    可以观察到,几乎不花时间,花费的时间在1毫秒以内

    HashMap的性能表现

    package collection;

      

    import java.util.HashMap;

      

    import charactor.Hero;

      

    public class TestCollection {

        public static void main(String[] args) {

              

            HashMap<String,Hero> heroMap = new HashMap<String,Hero>();

            for (int j = 0; j < 2000000; j++) {

                Hero h = new Hero("Hero " + j);

                heroMap.put(h.name, h);

            }

            System.out.println("数据准备完成");

      

            for (int i = 0; i < 10; i++) {

                long start = System.currentTimeMillis();

                  

                //查找名字是Hero 1000000的对象

                Hero target = heroMap.get("Hero 1000000");

                System.out.println("找到了 hero!" + target.name);

                  

                long end = System.currentTimeMillis();

                long elapsed = end - start;

                System.out.println("一共花了:" + elapsed + " 毫秒");

            }

      

        }

    }

    步骤 3 : HashMap原理与字典

    在展开HashMap原理的讲解之前,首先回忆一下大家初中和高中使用的汉英字典。

    比如要找一个单词对应的中文意思,假设单词是Lengendary,首先在目录找到Lengendary在第 555页。 

    然后,翻到第555页,这页不只一个单词,但是量已经很少了,逐一比较,很快就定位目标单词Lengendary。

    555相当于就是Lengendary对应的hashcode

    步骤 4 : 分析HashMap性能卓越的原因

    -----hashcode概念-----
    所有的对象,都有一个对应的hashcode(散列值)
    比如字符串“gareen”对应的是1001 (实际上不是,这里是方便理解,假设的值)
    比如字符串“temoo”对应的是1004
    比如字符串“db”对应的是1008
    比如字符串“annie”对应的是1008

    -----保存数据-----
    准备一个数组,其长度是2000,并且设定特殊的hashcode算法,使得所有字符串对应的hashcode,都会落在0-1999之间
    要存放名字是"gareen"的英雄,就把该英雄和名称组成一个键值对,存放在数组的1001这个位置上
    要存放名字是"temoo"的英雄,就把该英雄存放在数组的1004这个位置上
    要存放名字是"db"的英雄,就把该英雄存放在数组的1008这个位置上
    要存放名字是"annie"的英雄,然而 "annie"的hashcode 1008对应的位置已经有db英雄了,那么就在这里创建一个链表,接在db英雄后面存放annie

    -----查找数据-----
    比如要查找gareen,首先计算"gareen"的hashcode是1001,根据1001这个下标,到数组中进行定位,(根据数组下标进行定位,是非常快速的) 发现1001这个位置就只有一个英雄,那么该英雄就是gareen.
    比如要查找annie,首先计算"annie"的hashcode是1008,根据1008这个下标,到数组中进行定位,发现1008这个位置有两个英雄,那么就对两个英雄的名字进行逐一比较(equals),因为此时需要比较的量就已经少很多了,很快也就可以找出目标英雄
    这就是使用hashmap进行查询,非常快原理。


    这是一种用空间换时间的思维方式

    分析HashMap性能卓越的原因

    步骤 5 : HashSet判断是否重复

    HashSet的数据是不能重复的,相同数据不能保存在一起,到底如何判断是否是重复的呢?
    根据HashSet和HashMap的关系,我们了解到因为HashSet没有自身的实现,而是里面封装了一个HashMap,所以本质上就是判断HashMap的key是否重复。

    再通过上一步的学习,key是否重复,是由两个步骤判断的:
    hashcode是否一样
    如果hashcode不一样,就是在不同的坑里,一定是不重复的
    如果hashcode一样,就是在同一个坑里,还需要进行equals比较
    如果equals一样,则是重复数据
    如果equals不一样,则是不同数据。


    更多内容,点击了解: https://how2j.cn/k/collection/collection-hashcode/371.html

  • 相关阅读:
    函数调用栈的总结
    Calling convention-调用约定
    函数可以返回结构体的原因
    pthread_join/pthread_exit的用法解析
    线程退出的几种方式和资源回收【线程编程中避免内存泄漏】
    线程状态与tcb、线程的生命周期
    pthread_cleanup_push vs Autorelease VS 异常处理
    thread.h
    Thread Control Block
    线程与cpu
  • 原文地址:https://www.cnblogs.com/Lanht/p/12615488.html
Copyright © 2011-2022 走看看