Java HashMap的使用

来源:互联网 发布:这个驸马有淘宝(重生) 编辑:程序博客网 时间:2024/04/27 01:22

      最近在编码中经常用到HashMap,所得到的了解也仅限于《Java核心技术卷I》上面关于Map的简单介绍(get、put方法),但是对其背后具体实现尚没有了解。这个博文比较详细的说明了源码中HashMap的实现原理,java中HashMap详解

       简而言之就是一句关键话:当向 HashMap 中添加 key-value 对,由其 key 的 hashCode() 返回值决定该 key-value 对(就是 Entry 对象)的存储位置。当两个 Entry 对象的 key 的 hashCode() 返回值相同时,将由 key 通过 eqauls() 比较值决定是采用覆盖行为(返回 true),还是产生 Entry 链(返回 false)【注意key的hashcode相等并不是说key就相等,hashcode的计算是由初始化时桶的数目和装填因子来决定,肯定存在hashcode值相等,但key值不相等的情况。另外key值相等的话,hashcod那么肯定是相等的】。可以把value当做是key的附属,在前面考虑key-value对存在于HashMap表何处时,完全是用key值在计算,entry链上也是各个key值不同但是key的hashcode值相同的节点。

       最近做OJ也碰到已到可以采用HashMap方法解决的。Problem 1203 - 找相同   题目的意思就是输出出现次数超过一半的数,那么就直接对每个数计数就是。 构建HashMap表,其中输入的各个数字为key,数字出现的次数为value。 本题可以对每个输入元素,先用Map的 V get(K key)方法获得与键key(即每个输入的数字)对应的值value,如果该数字是第一次输入,那么get方法返回的是null值;如果不是则放回其对应的value值,也就是这个数字已经出现的次数。 那么就可以根据这个返回值来将包含这个数字的key-value对写入Map中:get方法返回null,key-value对为(数字,1);get方法返回的数字已经出现的次数 j,key-value对为(数字, j+1),这种情况下写入这个key-value对的时候,会覆盖之前的key-value对(数字, j)。键必须是唯一的,不能对同一个键存放两个值。当对同一个键两个调用put(K kye, V value)方法时,后面的value会覆盖前面的value,所以前面所说的 j+1 会覆盖 j。

       构建完HashMap表之后,那么表中的每个key就是输入的各数字,key相对应的value值就是这个数字出现的次数,那么调用int map.size() 方法就能够获得map中key值得数目,也就是这输入的一串数字中,值各不相同的数字的个数。 此时构建Map表的entry视图(调用map.entrySet()方法),用entry元素或者说是entry对象(key-value对)遍历整个Map表,由于entry元素就存在getKey()和getValue()方法,就很容易获得每一个key-value对的key值、value值,遍历后返回最大value值即可。虽然在Map中,由key值获得value值是简单的,直接调用V get(K key)方法即可,但是由于存在不同的key值可能对应值相同的value,那么不能直接 K get(V value) 方法直接返回value所对应的key值(也不直接存在这样的方法)。 要获得value对应的key值,也只能用entry元素遍历整个Map表,value值等于前面返回的最大value的entry元素(key-value对),就调用 getKey()方法获得value值对应的 key值。


    附录代码(没有考虑提交,输入项采用main入口函数的string参数)

package T_1203;// 题目的意思是要求输出次数过半的元素,可以采用Map来做统计各个数出现的次数import java.util.* ;public class Main{        public static void main(String args[])     {        Map<String, Integer> m = new HashMap<String, Integer>();                for(int i=0 ;i<args.length ;i++)         {            int j = (Integer)m.get(args[i]) == null ? 0 : (Integer)m.get(args[i]) ;            m.put(args[i] , (j == 0 ? 1 : j + 1)) ; //新出现数字则加入(数字,1),以前已出现数字就用(数字,j+1)覆盖之前的(数字,j)        }                Integer max = 0;                for(Map.Entry<String,Integer> entry: m.entrySet())  //构建map表的entry视图,遍历map的所有key——value对,获得value最大值        {        if(m.get(entry.getKey())> max)        max = m.get(entry.getKey());                }        List<String> list = new ArrayList<String>();                for(Map.Entry<String, Integer> entry:m.entrySet())  //既然不直接存在像 V get(K key)这样的K get(V value)这样的方法,那么就直接遍历整个map表        {        if(max == entry.getValue())        list.add(entry.getKey());        }        System.out.println(list.toString());        System.out.println(m) ;        } }


原创粉丝点击