zoukankan      html  css  js  c++  java
  • 第19章 集合框架(3)-Map接口

    第19章 集合框架(3)-Map接口

    1.Map接口概述

    Map是一种映射关系,那么什么是映射关系呢?
    映射的数学解释
    设A,B是两个非空集合,如果存在一个法则,使得对A中的每一个元素a,按法则f,在B中有唯一确定的元素b与之对应,则称f为A到B的映射,记作f:A-B.
    映射关系(对于A,B集合)
    A集合中的每一个元素都可以在B集合中找到唯一的一个值与之对应
    严格上来说Map并不是集合,不属于Collection接口,而是两个集合之间的映射关系,每次存储都应该存储A集合中一个元素(Key),B集合中一个元素(Value),我们还是习惯把Map也称之为集合

    因为Map接口并没有继承于Collection接口,也没有继承Iterable接口,所以不能直接对Map使用for-each操作,但是如果遍历的话,可以使用Map里面的一些特殊的方法来操作。

    存储过程中,key值不能重复,遵循Set集合,Value允许重复,遵循List集合

    2.Map中的常用操作方法

    Map是一个接口,此类型的常用方法以HashMap类为例,大部分都是通用的,如果需要特别的方法,可以查询api

    3.Set和Map之间的关系

    Map和Set中有很多相类似的实现类名:

    如果集合前缀相同,说明底层算法是一样的,现在单独使用HashSet和hashMap来研究
    通过阅读源码,发现相同算法的Set底层用的是相同算法的Map。把Set的集合对象作为Map的Key,再使用一个Object常量为value
    因此,更符合我们说的在Map中,所有的key就是一个Set集合

    4.Map的实现类和性能分析

    Map实现类:

    解释:
    HashMap:采用哈希表算法,此时Map中的Key不会保证添加的先后顺序,key也不允许重复。
    key判断重复的标准是:key1和key2是否equals为true,并且hashCode相等
    TreeMap:采用哈希算法:采用红黑树算法,此时Map中的key会按照自然顺序或定制顺序,key也不允许重复
    key判断重复的标准是:compareTo/compare的返回值是否为0

    LinkedHashMap:采用链表和哈希算法,此时Map中的key会保证先后添加顺序,key不允许重复。
    key判断重复的标准和HashMap中的key的标准相同

    Hashtable:采用哈希表算法,是hashMap的前身(类似Vector是ArrayList的前身)
    在java的集合框架之前,表示映射关系就使用Hashtable
    所有的方法都是使用synchronized修饰符,线程安全的,但是性能相对HashMap较低。打死不用

    Properties:Hashtable的子类,此时要求key和value都是String类型,用来加载资源文件

    一般的,我们定义map,key都使用不可变的类(String等),把key作为value的唯一名称
    如何选用
    HashMap和TreeMap以及LinkedHashMap都是线程不安全的,但是性能很高。
    解决方案Map m = Collections.synchronizedMap(Map对象);
    Hashtable类实现线程安全,但是性能低
    哈希算法作等值查询最快
    树结构算法,作范围查询最快,应用到索引上

    5.Map案例(计算字符中字符出现的次数)

    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 计算一个字符串中,每一个字符出现的次数
     */
    public class StringCount {
        public static void main(String[] args) {
            String str = "aqazasawsawsaws";
            //把字符串转换为char数组(字符串本质就是char[])
            char[] arr = str.toCharArray();
            //key:存储字符名,value:存储出现次数
            Map<Character, Integer> map = new HashMap<>();
            //循环得到每一个字符
            for (char ch:arr){
                //判断当前字符是否在Map中的key存在
                if (map.containsKey(ch)){
                    //当前Map的key包含该字符,此时取出该value,自增再存进去
                    Integer old = map.get(ch);
                    map.put(ch, old+1);
                }else {
                    //当前Map的key不包含该字符,把该字符存到Map中,设置value为1
                    map.put(ch,1);
                }
            }
            System.out.println(map);//{a=6, q=1, s=4, w=3, z=1}
        }
    }
    

    6.List和Set以及Map的选用

    选用哪一种容器取决于每一种容器的存储特点以及当前业务的需求
    List:单一元素集合
    允许元素重复/记录元素的添加顺序

    Set单一元素集合
    不允许元素重复/不及录元素的添加顺序

    既要不重复,又要保证先后顺序,可以使用:LinkedHashSet

    Map:双元素集合,如果存储数据的时候,还得给数据起一个名称时,此时考虑使用Map

    List, Set, Map之间的相互转换:
    List<String> list = new ArrayList<>();
    把List转换为Set:
    Set<String> set = new HashSet<>(list);
    把Set转换为List:
    List<String> list2 = new ArrayList<>(set);
    Map不能直接转换为List或Set,但是Map中的方法可以间接转换

    7.List和Map的综合应用

    Map在以后运用的非常广泛,比如可以表示javaBean对象,可以作缓存
    javaBean对象:多对,属性名=属性值
    Map对象;每一个key-value就好比一对属性名=属性值
    把Map对象转换为javaBean对象,把javaBean对象转换为Map对象
    Set,List,Map三种集合并不都是单独使用的,偶尔也会综合使用
    示例:

    public class StudentTest {
        public static void main(String[] args) {
            //使用Set集合存储一个班级学生的名称
            Set<String> name1 = new HashSet<>();
            name1.add("赵一");
            name1.add("李二");
            name1.add("张三");
            System.out.println(name1);//[李二, 张三, 赵一]
    
    
            Set<String> name2 = new HashSet<>();
            name2.add("西门大官人");
            name2.add("叶孤城");
            name2.add("陆小凤");
    
            //使用Map来存储多个班级的学生
            Map<String, Set<String>> classMap = new HashMap<>();
            classMap.put("初出茅庐",name1);
            classMap.put("登堂入室",name2);
            System.out.println(classMap);
            //{登堂入室=[西门大官人, 陆小凤, 叶孤城], 初出茅庐=[李二, 张三, 赵一]}
    
            Map<String, Set<String>> classMap2 = new HashMap<>();
            classMap2.put("初出茅庐",name1);
            classMap2.put("登堂入室",name2);
    
            //使用List来存储所有学院的学生姓名
            List<Map<String ,Set<String>>> school = new ArrayList<>();
            school.add(classMap);
            school.add(classMap2);
            System.out.println(school);
            //[{登堂入室=[西门大官人, 陆小凤, 叶孤城], 初出茅庐=[李二, 张三, 赵一]}, {登堂入室=[西门大官人, 陆小凤, 叶孤城], 初出茅庐=[李二, 张三, 赵一]}]
    
        }
    }
    
    
  • 相关阅读:
    UVa 12174 (滑动窗口) Shuffle
    UVa 1607 (二分) Gates
    CodeForces ZeptoLab Code Rush 2015
    HDU 1525 (博弈) Euclid's Game
    HDU 2147 (博弈) kiki's game
    UVa 11093 Just Finish it up
    UVa 10954 (Huffman 优先队列) Add All
    CodeForces Round #298 Div.2
    UVa 12627 (递归 计数 找规律) Erratic Expansion
    UVa 714 (二分) Copying Books
  • 原文地址:https://www.cnblogs.com/cenyu/p/6149805.html
Copyright © 2011-2022 走看看