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);
            //[{登堂入室=[西门大官人, 陆小凤, 叶孤城], 初出茅庐=[李二, 张三, 赵一]}, {登堂入室=[西门大官人, 陆小凤, 叶孤城], 初出茅庐=[李二, 张三, 赵一]}]
    
        }
    }
    
    
  • 相关阅读:
    【开发技术】Eclipse设置软tab(用4个空格字符代替)及默认utf-8文件编码(unix)
    【开发技术】Xcode3与xcode4.2模板对比(Xcode4.2开发之一些变化)
    cobol
    头文件的相互包含会导致错误
    ndk eclipse集成
    为何要用到NDK?
    Android之NDK开发
    一个完整的NDK编译过程
    NDK中 .so文件的加载
    Android.mk 变量解释
  • 原文地址:https://www.cnblogs.com/cenyu/p/6149805.html
Copyright © 2011-2022 走看看