zoukankan      html  css  js  c++  java
  • 集合查询表--Map

     查询表

     Map接口
    java提供了一组可以以键值对(key-value)的形式存储数据的数据结构,这种数据结构成为Map。我们可以把Map看成一个多行两列的表格,其中第一列存放key,第二列存放value。
    而每一行就相当于一组key-value对,表示一组数据。
    Map对存入的元素有一个要求,就是key不能重复,所谓不能重复指的是在Map中不能包含两个equals为true的key。
    Map对于key,value的类型没有严格要求,只要是引用类型均可。但是为了保证在使用时不会造成数据混乱,通常我们会使用泛型去约束key与value的类型。


    1. put方法

    既然我们知道了Map在保存数据时实际上是存入了两部分信息的 ,key与value。那么我们来看看如何向Map中存入数据。
    Map提供了一个方法:
    V put(K k,V v)
    该方法的作用是将key-value对存入Map中,因为Map中不允许出现重复的key,所以若当次存入的key已经在Map中存在,则是替换value操作,而返回值则为被替换的元素。若次key不存在,那么返回值为null。
    2. get方法法

    我们学会了如何向Map中存入数据,那么我们再来看看如何获取数据。Map中获取数据的方式是给定Key获取对应的Value。
    Map提供了一个方法:
    V get(Object key)
    该方法的作用就是根据给定的key去查找Map中对应的value并返回,若当前Map中不包含给定的key,那么返回值为null。
    3. containsKey方法

    Map中的containsKey方法用于检测当前Map中是否包含给定的key。其方法定义如下:
    boolean containsKey(Object key)
    若当前Map中包含给定的key(这里检查是否包含是根据key的equals比较结果为依据的。)则返回true。

    class TestSet2{
        /*
         * Map要求两个泛型 分别用来约束key的类型与value的类型
         * 
         * 什么时候要用map?
         * 通常我们保存一组数据,而每个数据若需要说明则可以使用map
         * key: 保存说明
         * value:保存数据
         */
        static Map<String,Integer> map = new HashMap<String,Integer>(); 
        /*
         * 统计各个检测站的PM2.5
         */
        public static void main(String[] args) {
            String pm25="东四=423,丰台花园=378,天坛=406,"+
                        "海淀区万柳=322,官园=398,通州=406,"+
                        "昌平镇=366,怀柔镇=248,定陵=306,"+
                        "前门=231,永乐店=422,古城=368,"+
                        "昌平镇=268,怀柔镇=423,定陵=267,"+
                        "前门=377,永乐店=299,秀水街=285";
            String[] arr = pm25.split("[ = ,]");
            System.out.println(Arrays.toString(arr));
            System.out.println(arr.length);
            
            for(int i=0;i<arr.length;i+=2){
                String name = arr[i];
                int pm =Integer.parseInt(arr[i+1]);
                //将每一项存入map中
                /*
                 * 首先查看当前站点名字是否在map中已经存在了
                 *     -直接将站点与pm存入即可
                 * 若存在:
                 *     -将map中该站点的pm值取出
                 *     -与这次的pm比较,谁打谁存入map
                 */
                
                /*
                 * 查看map中是否包含给定的key
                 * boolean containsKey(k k)
                 * 这里检查也是使用key的equals方法比较的
                 */
                if(map.containsKey(name)){
                    /*
                     * V get(k k)
                     *根据给定的key获取map中对应的value
                     *若key在map中不存在则返回值为null
                     */
                    int oldpm =map.get(name);
                    if(oldpm<pm){
                        //返回的事被替换的值
                        map.put(name,pm);
                    }
                    
                }else{
                    map.put(name,pm);
                }
                
            }
            /*
             * put方法会将给定的key与value存入map
             * 当若给定的key已经在map中存在,则替换value操作
             * put方法返回值为被替换的value
             */
            System.out.println(map);
        }
    }
    /**
     * 测试Map
     * @author Administrator
     *
     */
    class TestSet3{
        public static void main(String[] args) {
            /*
             * 保存学员的年龄
             */
            Map<String,Integer> map =new HashMap<String,Integer>();
            map.put("张三",22);
            map.put("李四",17);
            map.put("王五",14);
            map.put("赵六",35);
            map.put("阿拉丁",44);
            map.put("阿拉甲",32);
            map.put("阿拉乙",59);
            map.put("阿拉丙",18);
            //获取赵六的名字
            int age =map.get("赵六");
            System.out.println("赵六的年龄是:"+age);
            System.out.println(map.put("赵六",22));
        }
    }

    HashMap
    1. hash表原理

    HashMap是Map的一个常用的子类实现。其实使用散列算法实现的。
    HashMap内部维护着一个散列数组(就是一个存放元素的数组),我们称其为散列桶,而当我们向HashMap中存入一组键值对时,HashMap首先获取key这个对象的hashcode()方法的返回值,然后使用该值进行一个散列算法,得出一个数字,这个数字就是这组键值对要存入散列数组中的下标位置。
    那么得知了下标位置后,HashMap还会查看散列数组当前位置是否包含该元素。(这里要注意的是,散列数组中每个元素并非是直接存储键值对的,而是存入了一个链表,这个链表中的每个节点才是真实保存这组键值对的。)检查是否包含该元素时根据当前要存入的key在当前散列数组对应位置中的链表里是否已经包含这个key,若不包含则将这组键值对存入链表,否则就替换value。
    那么在获取元素时,HashMap同样先根据key的hashcode值进行散列算法,找到它在散列数组中的位置,然后遍历该位置的链表,找到该key所对应的value之后返回。
    看到这里可能有个疑问,链表中应该只能存入一个元素,那么HashMap是如何将key-value存入链表的某个节点的呢?实际上,HashMap会将每组键值对封装为一个Entry的实例,然后将该实例存入链表。

    2. hashcode方法

    HashMap的存取是依赖于key的hashcode方法的返回值的,而hashcode方法实际上是在Object中定义的。其定义如下:
    int hashCode()
    重写一个类的hashcode()方法有以下注意事项:
    若一个类重写了equals方法,那么就应当重写hashcode()方法。
    若两个对象的equals方法比较为true,那么它们应当具有相同的hashcode值。
    对于同一个对象而言,在内容没有发生改变的情况下,多次调用hashCode()方法应当总是返回相同的值。
    对于两个对象equals比较为false的,并不要求其hashcode值一定不同,但是应尽量保证不同,这样可以提高散列表性能。

    在生成equals与hashcode时,应选中equals比较中需要参与的属性即可

    3. 装载因子及HashMap优化

    在散列表中有一下名词需要了解:
    Capacity:容量, hash表里bucket(桶)的数量, 也就是散列数组大小.
    Initial capacity:初始容量, 创建hash表的时 初始bucket的数量, 默认构建容量是16. 也可以使用特定容量.
    Size : 大小, 当前散列表中存储数据的数量.
    Load factor:加载因子, 默认值0.75(就是75%), 当向散列表增加数据时如果 size/capacity 的值大于Load factor则发生扩容并且重新散列(rehash).
    那么当加载因子较小时候散列查找性能会提高, 同时也浪费了散列桶空间容量. 0.75是性能和空间相对平衡结果. 在创建散列表时候指定合理容量, 从而可以减少rehash提高性能。
    有序Map
     LinkedHashMap实现有序的Map

    Map 接口的哈希表和链表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,LinkedHashMap维护着一个双向循环链表。此链表定义了迭代顺序,该迭代顺序通常就是将存放元素的顺序。
    需要注意的是,如果在Map中重新存入以有的key,那么key的位置会不会发生改变,只是将value值替换。

  • 相关阅读:
    牛客练习赛51 D题
    Educational Codeforces Round 72 (Rated for Div. 2) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) C题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Codeforces Round #583 (Div. 1 + Div. 2, based on Olympiad of Metropolises) A题
    Educational Codeforces Round 72 (Rated for Div. 2) B题
    Educational Codeforces Round 72 (Rated for Div. 2) A题
    《DSP using MATLAB》Problem 7.2
    《DSP using MATLAB》Problem 7.1
    《DSP using MATLAB》Problem 6.24
  • 原文地址:https://www.cnblogs.com/manue1/p/4497072.html
Copyright © 2011-2022 走看看