Java学习13-集合-2

Java学习13-集合-2

7.Map接口

7.1 Map接口概述

在这里插入图片描述

  • Map与Collection并列存在。用于保存具有 映射关系的数据:key-value
  • Map 中的 key 和 value 都可以是任何引用类型的数据
  • Map 中的 key 用Set来存放, 不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法
  • 常用String类作为Map的“键”
  • key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value
  • Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和Properties。其中,HashMap是 Map 接口使用频率最高的实现类

7.2 Map接口:常用方法

  • 添加 、 删除、修改操作 :
    • Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
    • void putAll(Map m):将m中的所有key-value对存放到当前map中
    • Object remove(Object key):移除指定key的key-value对,并返回value
    • void clear():清空当前map中的所有数据
  • 元素查询的操作:
    • Object get(Object key):获取指定key对应的value
    • boolean containsKey(Object key):是否包含指定的key
    • boolean containsValue(Object value):是否包含指定的value
    • int size():返回map中key-value对的个数
    • boolean isEmpty():判断当前map是否为空
    • boolean equals(Object obj):判断当前map和参数对象obj是否相等
  • 元素视图操作的方法:
    • Set keySet():返回所有key构成的Set集合
    • Collection values():返回所有value构成的Collection集合
    • Set entrySet():返回所有key-value对构成的Set集合

【例】

import java.util.*;

public class MapTest {

    public static void main(String[] args) {
        MapTest mt = new MapTest();
       // mt.test1();
        //mt.test2();
        mt.test3();
    }

    /**
     * 添加、删除、修改
     * - Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
     * - void putAll(Map m):将m中的所有key-value对存放到当前map中
     * - Object remove(Object key):移除指定key的key-value对,并返回value
     * - void clear():清空当前map中的所有数据
     */
    public void test1() {
        Map map = new HashMap();
        //put()
        map.put("AA",123);
        map.put("BB",45);
        map.put("DD",78);
        map.put("CC",67);
        //put()
        map.put("DD",89);

        System.out.println(map);
        //{AA=123, BB=45, DD=89, CC=67}

        Map map1 = new HashMap();
        map1.put("aa",123);
        map1.put("bb",123);
        //putAll()
        map.putAll(map1);

        System.out.println(map);
        //{AA=123, BB=45, DD=89, CC=67, aa=123, bb=123}

        //remove()
        Object cc = map.remove("CC");
        System.out.println(cc);//67
        System.out.println(map);//{AA=123, BB=45, DD=89, aa=123, bb=123}

        //clear()
        map.clear();//与map = null操作不同
        System.out.println(map);//{}
        System.out.println(map.size());//0
    }


    /**
     * 元素查询的操作:
     *   - Object get(Object key):获取指定key对应的value
     *   - boolean containsKey(Object key):是否包含指定的key
     *   - boolean containsValue(Object value):是否包含指定的value
     *   - int size():返回map中key-value对的个数
     *   - boolean isEmpty():判断当前map是否为空
     *   - boolean equals(Object obj):判断当前map和参数对象obj是否相等
     */
    public void test2() {
        Map map = new HashMap();
        map.put("AA",123);
        map.put("BB",45);
        map.put("DD",78);
        map.put("CC",123);
        map.put("DD",89);

        Map map1 = new HashMap();
        map1.put("AA",123);
        map1.put("BB",45);
        map1.put("DD",78);
        map1.put("CC",123);
        map1.put("DD",89);

        //get()
        System.out.println(map.get("AA"));//123

        //containsKey()
        System.out.println(map.containsKey("BB"));//true

        //containsValue()
        System.out.println(map.containsValue(123));//true

        //size()
        System.out.println(map.size());//4

        //isEmpty()
        map.clear();
        System.out.println(map.isEmpty());//true

        //equals()
        System.out.println(map.equals(map1));//false(地址不同)
    }

    /**
     * 元素视图操作的方法:
     *   - Set keySet():返回所有key构成的Set集合
     *   - Collection values():返回所有value构成的Collection集合
     *   - Set entrySet():返回所有key-value对构成的Set集合
     */
    public void test3(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put("BB",45);
        map.put("DD",78);
        map.put("CC",123);
        map.put("DD",89);

        //遍历所有的key集:keySet()
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
//            AA
//            BB
//            DD
//            CC

        }

        System.out.println();

        //遍历所有的value集:values()
        Collection values = map.values();

        Iterator iterator1 = values.iterator();
        while (iterator1.hasNext()){
            System.out.println(iterator1.next());
        }

//        for (Object obj:values) {
//            System.out.println(obj);
//        }

//        123
//        45
//        89
//        123

        System.out.println();

        //遍历所有的key-value集:
        // 方式一:entrySet()
        Set set1 = map.entrySet();
        Iterator iterator2 = set1.iterator();
        while (iterator2.hasNext()){
            Object obj=iterator2.next();
            Map.Entry entry=(Map.Entry)obj;
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
//        AA--->123
//        BB--->45
//        DD--->89
//        CC--->123

        System.out.println();

        //方式二:
        Set set2 = map.keySet();
        Iterator iterator3 = set2.iterator();
        while (iterator3.hasNext()){
            Object next = iterator3.next();
            Object o = map.get(next);
            System.out.println(next + "--->" + o);
        }
//        AA--->123
//        BB--->45
//        DD--->89
//        CC--->123



    }
}

7.3 Map 实现类之一:HashMap(重要)

  • HashMap是 Map 接口使用频率最高的实现类。效率高,但是线程不安全
  • 允许使用null键和null值,与HashSet一样,不保证映射的顺序。
  • 所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写:equals()hashCode()
  • 所有的value构成的集合是Collection:无序的、可以重复的。所以,value所在的类要重写:equals()
  • 一个key-value构成一个entry
  • 所有的entry构成的集合是Set:无序的、不可重复
  • HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
  • HashMap 判断两个 value 相等的标准是:两个 value 通过 equals() 方法返回 true。

HashMap的底层实现原理
HashMap map = new HashMap();
在实例化以后,底层创建了长度是16的一维数组Entry[ ] table
map.put(key1, value1);

  • 首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到Entry数组中的存放位置:
    • 如果此位置上的数据为空,此时的key1-value1添加成功--------->情况1
    • 如果此位置上的数据不为空(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
      • 如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value添加成功-------->情况2
      • 如果key1的哈希值与已经存在的某一个数据(key2-value)的哈希值相同,继续比较:调用key1所在类的equals(key2)
        • 如果equals()返回false:此时key1-value1添加成功-------->情况3
        • 如果equals()返回true:使用value1 替换 value2

补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储
在不断地添加过程中,会涉及到扩容问题,默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来
jdk8 相较于 jdk7在底层实现方面的不同

  1. new HashMap():底层没有创建一个长度为16的数组
  2. jdk 8 底层的数组是Node[ ] ,而非Entry[ ]
  3. 首次调用put()方法时,底层创建长度为16的数组
  4. jdk 7 底层结构只有:数组+链表。jdk 8 中底层结构:数组+链表+红黑树
    当数组的某一个索引位置上的元素以链表形式存在的数据个数 >8 且当前数组的长度 >64时,此时索引位置上的所有数据使用红黑树存储(优化查找效率)

7.4 Map 实现类之二:LinkedHashMap

  • LinkedHashMap 是 HashMap 的子类
  • 在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序,使得在遍历map时,可以按照添加的顺序遍历
  • 执行效率高于HashMap
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class MapTest {

    public static void main(String[] args) {
        MapTest mt = new MapTest();
        mt.test1();
        mt.test2();
    }

    public void test1() {
        Map map = new HashMap();
        map.put(123, "AA");
        map.put(456, "BB");
        map.put(12, "CC");

        System.out.println(map);//{456=BB, 123=AA, 12=CC}

    }

    public void test2() {
        Map map = new LinkedHashMap();
        map.put(123, "AA");
        map.put(456, "BB");
        map.put(12, "CC");

        System.out.println(map);//{123=AA, 456=BB, 12=CC}
    }
}

7.5 Map 实现类之三:TreeMap

  • TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。
  • TreeSet底层使用 红黑树结构存储数据
  • TreeMap 的 Key 的排序:
    • Key的自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
    • Key的定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现Comparable 接口
  • TreeMap判断两个key 相等的标准:两个key通过compareTo()方法或者compare()方法返回0。

【例】

import java.util.*;

public class TreeMapTest {
    //向TreeMap中添加key-value,要求key必须是由同一个类创建的对象
    //因为要按照key进行排序:自然排序、定制排序

    public static void main(String[] args) {
        TreeMapTest treeMapTest = new TreeMapTest();
        treeMapTest.test1();
        System.out.println();
        treeMapTest.test2();

    }

    /**
     * 自然排序
     */
    public void test1() {
        TreeMap treeMap = new TreeMap();
        User user1 = new User("Tom", 23);
        User user2 = new User("Jack", 37);
        User user3 = new User("Jerry", 28);
        User user4 = new User("Rose", 32);
        treeMap.put(user1, 98);
        treeMap.put(user2, 78);
        treeMap.put(user3, 88);
        treeMap.put(user4, 97);

        Set set1 = treeMap.entrySet();
        Iterator iterator2 = set1.iterator();
        while (iterator2.hasNext()) {
            Object obj = iterator2.next();
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
//        User{name='Jack', age=37}--->78
//        User{name='Jerry', age=28}--->88
//        User{name='Rose', age=32}--->97
//        User{name='Tom', age=23}--->98
    }

    /**
     * 定制排序
     */
    public void test2() {
        TreeMap treeMap = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof User && o2 instanceof User) {
                    User u1 = (User) o1;
                    User u2 = (User) o2;
                    return Integer.compare(u1.getAge(), u2.getAge());
                }
                throw new RuntimeException("输入的类型不匹配");
            }
        });
        User user1 = new User("Tom", 23);
        User user2 = new User("Jack", 37);
        User user3 = new User("Jerry", 28);
        User user4 = new User("Rose", 32);
        treeMap.put(user1, 98);
        treeMap.put(user2, 78);
        treeMap.put(user3, 88);
        treeMap.put(user4, 97);

        Set set1 = treeMap.entrySet();
        Iterator iterator2 = set1.iterator();
        while (iterator2.hasNext()) {
            Object obj = iterator2.next();
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
    }
//    User{name='Tom', age=23}--->98
//    User{name='Jerry', age=28}--->88
//    User{name='Rose', age=32}--->97
//    User{name='Jack', age=37}--->78


}

7.6 Map 实现类之四:Hashtable

  • Hashtable是个古老的 Map 实现类,JDK1.0就提供了。不同于HashMap,Hashtable是线程安全的,效率低。
  • Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询速度快,很多情况下可以互用
  • 与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value
  • 与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
  • Hashtable判断两个key相等、两个value相等的标准,与HashMap一致。

7.7 Map 实现类之五:Properties

  • Properties 类是 Hashtable 的子类,该对象用于处理属性文件
  • 由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key和 value 都是字符串类型
  • 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法
Properties pros = new Properties();
pros.load(new FileInputStream("jdbc.properties"));
String user = pros.getProperty("user");
System.out.println(user);

8.Collections 工具类

Collections 是一个操作 Set、List 和 Map 等集合的工具类
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法:

  • 排序操作:(均为static 方法)
    • reverse(List):反转 List 中元素的顺序
    • shuffle(List):对 List 集合元素进行随机排序
    • sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
    • sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
    • swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
  • 查找、替换
    • Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
    • Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
    • Object min(Collection)
    • Object min(Collection,Comparator)
    • int frequency(Collection,Object):返回指定集合中指定元素的出现次数
    • void copy(List dest,List src):将src中的内容复制到dest中
    • boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List 对象的所有旧值

猜你喜欢

转载自blog.csdn.net/qq_42145862/article/details/89293017