Map

Map_put_get.java

/**
 * java.util.Map
 * Map在实际开发中是一种非常常用的数据结构。
 * 存储元素看起来像是一个"多行两列的表格"。
 * Map中每个元素有两部分组成,分别为key,value
 * 俗称:键值对
 * 而从Map中查询数据的原则是根据key查找对应的value。
 * 所以Map要求key不允许重复(Map中不允许有key的equals
 * 比较为true.)
 * 
 * Map是一个接口,规定了Map这种数据结构操作的相关方法。
 * 常用实现类:java.util.HashMap(俗称:散列表,哈希表)
 * 
 * @author soft01
 *
 */
public class pm01_Map_put_get {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<String,Integer>();
        
        /*
         * V put (K k,V v)
         * 将给定的key-value对存入Map中。
         * 由于Map中不允许出现重复的key,所以
         * 若使用Map中已经存在的key存入一个新
         * 的value时,是做替换value操作,那么put
         * 方法的返回值就为该key原来对应的value,
         * 即:返回被替换的value
         * 若指定的key在Map中不存在,则存入后返回
         * 值为NULL.
         */
        Integer num = map.put("语文", 99);
        System.out.println(num);
        map.put("数学", 89);
        map.put("英语", 97);
        map.put("物理", 98);
        map.put("化学", 95);
        System.out.println(map);
        
        //重复的key则是替换value操作
        num = map.put("语文", 77);
        System.out.println(num);
        System.out.println(map);
        
        /*
         * V get(K k)
         * 根据给定的key获取对应的value,若
         * 给定的key在Map中不存在,则返回值为null
         */
        num = map.get("数学");
        System.out.println("数学:"+num);
        
        /*
         * V remove(K k)
         * 将给定的key所对应的键值对从当前Map中
         * 删除,返回值为该key所对应的value值。
         */
        num = map.remove("语文");
        System.out.println(map);
        System.out.println("old:"+num);
        
        System.out.println("size:"+map.size());
        
        boolean tf = map.containsKey("体育");
        System.out.println("key是否包含:"+tf);
        
        tf = map.containsValue(97);
        System.out.println("value是否包含:"+tf);
    }
}

Map_iterate.java


/**
 * Map的遍历
 * 遍历Map有三种方式:
 * 1:遍历所有的key
 * 2:遍历所有的键值对(Entry)
 * 3:遍历所有的value(用的比较少)
 * @author soft01
 *
 */
public class am01_Map_iterate {
    public static void main(String[] args) {
//      Map<String,Integer> map = new HashMap<String,Integer>();
        /*
         * LinkedHashMap是可以按照put元素时的顺序
         * 遍历Map中的所有元素
         */
        Map<String,Integer> map = new LinkedHashMap<String,Integer>();
        map.put("语文", 99);
        map.put("数学", 89);
        map.put("英语", 97);
        map.put("物理", 98);
        map.put("化学", 95);
        System.out.println(map);
        
        /*
         * HashMap本身不是线程安全的
         * 若希望将现有的Map转换为线程安全的,
         * 可以使用Collections的静态方法将其
         * 转换。
         */
        map = Collections.synchronizedMap(map);
        
        /*
         * 遍历所有的key
         * Set<K> keySet()
         * 将当前Map中所有的key存入一个Set集合后
         * 返回。
         */
        Set<String> keySet = map.keySet();
        keySet.forEach((k)->System.out.println(k));
        
        /*
         * 遍历所有的键值对
         * Map中每一组键值对由内部类Entry的实例表示
         * Entry有两个常用方法:
         * getKey,getValue.这两个方法用于获取当前
         * Entry实例表示的这组键值对中的key与value
         * 
         * set<Entry> entrySet()
         * 将当前Map中每组键值对存入一个Set集合后返回
         */
        Set<Entry<String,Integer>> entrySet = map.entrySet();
        for(Entry<String,Integer> e : entrySet) {
            String key = e.getKey();
            Integer value = e.getValue();
            System.out.println(key+":"+value);
        }
        
        /*
         * 将当前Map中所有的Value存入一个集合后
         * 返回。
         */
        Collection<Integer> values = map.values();
        for(Integer value : values) {
            System.out.println(value);
        }
        
    }
}

Key

/**
 * HashMap内部由数组实现,是当今查询速度最快的
 * 数据结构。
 * HashMap根据key元素决定这组键值对应当存放在
 * 数组的位置,并且也是根据key元素得到位置来检索
 * 数组中键值对以此省去了遍历数组的过程。
 * 
 * 但是使用HashMap时应当尽量避免出现链表的情况。
 * HashMap中链表产生的原因:
 * HashMap是根据key元素的hashcode方法返回的数字
 * 经过散列计算得到该键值对应当存放在数组的哪个
 * 位置,而根据key元素equals比较查看当前key是否
 * 已经存在于map中,若存在则直接替换该位置这个key
 * 所对应的value,但是若数组该位置已经存在键值对,
 * 并且key与当前准备存放的键值对中的Key的equals
 * 比较不同时,则会在数组当前位置产生链表。这样在
 * 将来根据key检索时会出现遍历链表的时候就会在
 * HashMap中产生链表,影响查询性能。
 * 
 * 总结:当key元素hashcode值相同,但是equals比较不同
 * 时就会在HashMap中产生链表,影响查询性能。
 * 
 * JDK中提供的类作为key元素没问题,都已妥善处理完毕。
 * 当我们自己定义的类需要作为key元素时,也要妥善的
 * 重写上述的两个方法。
 * 
 * 在API手册的Object类中对equals,hascode方法的
 * 重写有相关说明。重写准则:
 1:成对重写,即:当我们需要重写一个类的equals方法
 时,就应当连同重写hashcode方法。
 2:一致性,即:当两个对象equals比较为true时,hascode
    返回的数字应当相等。反之亦然,因为若两个对象equals
    比较返回不同但是hashcode相等时在HashMap中会产生链表。
 3:hashcode的稳定性,即:当参与equals比比较的属性值没有
    发生改变的前提下,多次调用hashcode方法返回的数字应当
    相等,不应当变化。
 * @author soft01
 *
 */
public class am02_Key {
    private int x;
    private int y;
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        am02_Key other = (am02_Key) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }
}

October 17, 2017 9:26 PM
2017.10.17

推荐阅读更多精彩内容