必看必学必完成Java学习笔记

深入了解Map

2017-07-26  本文已影响15人  kangyiii

联系

Java中的Map类似于OC的Dictionary,都是一个个键值对组成,一键对应一值。我在之前的文章中讲解过Set,其实在JAVA底层Set依赖的也是Map,那我们都知道,Set是单列的(只有值),而Map是双列的,怎么会是Set依赖Map呢?其实做法也很简单,Set将Key隐藏,只允许访问value就实现了Set的单列效果。

功能

*a:添加功能
    * V put(K key,V value):添加元素。
        * 如果键是第一次存储,就直接存储元素,返回null
        * 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
Map<String, Interger> map = new HashMap();
map.put("张三",23);

这里需要注意Map中的重复的键不存储,值覆盖返回

* b:删除功能
    * void clear():移除所有的键值对元素
    * V remove(Object key):根据键删除键值对元素,并把值返回
Map<String, Interger> map = new HashMap();
map.put("张三",23);
map.remove("张三");根据键删除元素
* c:判断功能
    * boolean containsKey(Object key):判断集合是否包含指定的键
    * boolean containsValue(Object value):判断集合是否包含指定的值
    * boolean isEmpty():判断集合是否为空
Map<String, Interger> map = new HashMap();
map.put("张三",23);
System.out.println(map.containsKey("张三"));      //判断集合是否包含指定的键
System.out.println(map.containsValue(100));         //判断集合是否包含指定的值
* d:获取功能
    * Set<Map.Entry<K,V>> entrySet():
    * V get(Object key):根据键获取值
    * Set<K> keySet():获取集合中所有键的集合
    * Collection<V> values():获取集合中所有值的集合
Map<String, Interger> map = new HashMap();
map.put("张三",23);
Collection<Integer> c = map.values();
* e:长度功能
    * int size():返回集合中的键值对的个数
Map<String, Interger> map = new HashMap();
map.put("张三",23);
System.out.println(map.size());  

size()方法以键值对的个数统计,上述map.size()为1而不是2。

Map的遍历

方式一
  //通过获取所有的键来遍历值
        Map<String, Integer> map = new HashMap<>();
        map.put("张三", 23);
        map.put("李四", 24);
        map.put("王五", 25);
        map.put("赵六", 26);

        Set<String> keySet = map.keySet();          //获取所有键的集合
        Iterator<String> it = keySet.iterator();    //获取迭代器
        while(it.hasNext()) {                       //判断集合中是否有元素
            String key = it.next();                 //获取每一个键
            Integer value = map.get(key);           //根据键获取值
            System.out.println(key + "=" + value);
        }

使用迭代器遍历,但是有些复杂,可以改进

方式二 (方式一改进,较简单)

这种遍历方式类似于OC中for···in语法

        //使用增强for循环遍历
        for(String key : map.keySet()) {            //map.keySet()是所有键的集合
            System.out.println(key + "=" + map.get(key));
        }
方式三 键值对对象遍历
        //Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        //获取每一个对象
        Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
        while(it.hasNext()) {
            //获取每一个Entry对象
            Map.Entry<String, Integer> en = it.next();  //父类引用指向子类对象
            //Entry<String, Integer> en = it.next();    //直接获取的是子类对象
            String key = en.getKey();                   //根据键值对对象获取键
            Integer value = en.getValue();              //根据键值对对象获取值
            System.out.println(key + "=" + value);
        }
方式四 (方式三改进)
        for(Entry<String, Integer> en : map.entrySet()) {
            System.out.println(en.getKey() + "=" + en.getValue());
        }

LinkedHashMap

LinkedHashMap可以保证怎么存就怎么取

    public static void main(String[] args) {
        LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
        lhm.put("张三", 23);
        lhm.put("李四", 24);
        lhm.put("赵六", 26);
        lhm.put("王五", 25);
        
        System.out.println(lhm);
    }

TreeMap

利用TreeMap可实现对键的自定义排序,同时键应为自定义类对象,同时需要在自定义类中重写compareTo方法,和hashSet里面的排序大致相同。

//按照Student的姓名排序,姓名相同按照年龄排序
public static void main(String[] args) {
        //demo1();
        TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {

            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getName().compareTo(s2.getName());     //按照姓名比较
                return num == 0 ? s1.getAge() - s2.getAge() : num;
            }
        });
        tm.put(new Student("张三", 23), "北京");
        tm.put(new Student("李四", 13), "上海");
        tm.put(new Student("赵六", 43), "深圳");
        tm.put(new Student("王五", 33), "广州");
        
        System.out.println(tm);
    }

利用HashMap统计字符串中每个字符出现的次数

核心思想就是利用HashMap的containsKey()来判断是否重复。

/**
     * * A:案例演示
     * 需求:统计字符串中每个字符出现的次数
     * 
     * 分析:
     * 1,定义一个需要被统计字符的字符串
     * 2,将字符串转换为字符数组
     * 3,定义双列集合,存储字符串中字符以及字符出现的次数
     * 4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
     * 5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,如果集合中包含这个键,就将值加1存储
     * 6,打印双列集合获取字符出现的次数
     */
    public static void main(String[] args) {
        //1,定义一个需要被统计字符的字符串
        String s = "aaaabbbbbccccccccccccc";
        //2,将字符串转换为字符数组
        char[] arr = s.toCharArray();
        //3,定义双列集合,存储字符串中字符以及字符出现的次数
        HashMap<Character, Integer> hm = new HashMap<>();
        //4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
        for(char c: arr) {
            //5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,如果集合中包含这个键,就将值加1存储
            /*if(!hm.containsKey(c)) {          //如果不包含这个键
                hm.put(c, 1);
            }else {
                hm.put(c, hm.get(c) + 1);
            }*/
            hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
        }
        //6,打印双列集合获取字符出现的次数
        
        for (Character key : hm.keySet()) {             //hm.keySet()代表所有键的集合
            System.out.println(key + "=" + hm.get(key));//hm.get(key)根据键获取值
        }
    }
案例演示:

集合嵌套之HashMap嵌套HashMap

需求:

一个年级有很多班,
一班定义为一个双列结合,键是学生对象,值是学生的归属地,
二班定义为一个双列结合,键是学生对象,值是学生的归属地。
无论一班二班都是班级对象,所以为了编译统一管理,把这些班级对象添加到某个年级中。

        //定义一班
        HashMap<Student, String> hm88 = new HashMap<>();
        hm88.put(new Student("张三", 23), "北京");
        hm88.put(new Student("李四", 24), "北京");
        hm88.put(new Student("王五", 25), "上海");
        hm88.put(new Student("赵六", 26), "广州");
        
        //定义二班
        HashMap<Student, String> hm99 = new HashMap<>();
        hm99.put(new Student("唐僧", 1023), "北京");
        hm99.put(new Student("孙悟空",1024), "北京");
        hm99.put(new Student("猪八戒",1025), "上海");
        hm99.put(new Student("沙和尚",1026), "广州");
        
        //定义年级
        HashMap<HashMap<Student, String>, String> hm = new HashMap<>();
        hm.put(hm88, "一班");
        hm.put(hm99, "二班");
        
        //遍历双列集合
        for(HashMap<Student, String> h : hm.keySet()) {     //hm.keySet()代表的是双列集合中键的集合
            String value = hm.get(h);                       //get(h)根据键对象获取值对象
            //遍历键的双列集合对象
            for(Student key : h.keySet()) {                 //h.keySet()获取集合总所有的学生键对象
                String value2 = h.get(key);
                
                System.out.println(key + "=" + value2 + "=" + value);
            }
        }

hashMap和hashTable的区别

共同点:

底层都是哈希算法,都是双列集合

区别:
  1. HashMap是线程不安全的,效率高,JDK1.2版本,Hashtable是线程安全的,效率低,JDK1.0版本的
  2. HashMap可以存储null键和null值,Hashtable不可以存储null键和null值
上一篇下一篇

猜你喜欢

热点阅读