15 Java中Map集合的介绍

Map

一、Map集合

1. Map集合概述

  • java.util.Map<k,v>集合
  • 特点:
    • Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)。
    • Map集合中的元素,keyvalue的数据类型可以相同,也可以不同。
    • Map集合中的元素,key是不允许重复的,value是可以重复的。
    • Map集合中的元素,keyvalue是一一对应的。

2. Map常用子类

  • java.util.HashMap<k,v>集合 implements Map<k,v>接口
  • 特点:
    • HashMap集合底层是哈希表:查询的速度特别快。
      • JDK1.8之前:数组 + 单向链表;
      • JDK1.8之后:数组 + 单向链表/红黑树(链表长度超过8):提高查询的速度。
    • HashMap集合是一个无序集合,存储元素和取出元素的顺序有可能不一致。
  • java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
    • 特点:
      • LinkedHashMap集合底层是哈希表 + 链表(保证迭代的顺序);
      • LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的。

3. Map接口中的常用方法

  • public V put(K key, V value)把指定的键与指定的值添加到Map集合中。

    • Map中该key不存在,则插入该键值对,返回null
    • Map中该key存在,则替换该key对应的value,返回被替换的value
    import java.util.HashMap;
    
    public class Test01 {
        public static void main(String[] args) {
            HashMap<String, Integer> hashMap = new HashMap<>();
            Integer v1 = hashMap.put("朱古力", 15);
            System.out.println(v1);  // null
            Integer v2 = hashMap.put("朱古力", 18);
            System.out.println(v2);  // 15
            hashMap.put("猪猪侠", 20);
            hashMap.put("猪猪猪", 22);
            System.out.println(hashMap); // {猪猪猪=22, 朱古力=18, 猪猪侠=20}
        }
    }
    
  • public V remove(Object key)把指定的键所对应的键值对元素在Map集合中删除,返回删除元素的值。

    • Map中该key不存在,则返回null
    • Map中该key存在,则删除该键值对,返回被删除的value
    import java.util.HashMap;
    
    public class Test02 {
        public static void main(String[] args) {
            HashMap<String,Integer> hashMap = new HashMap<>();
            hashMap.put("朱古力", 18);
            hashMap.put("猪猪侠", 20);
            hashMap.put("猪猪猪", 22);
            System.out.println(hashMap);  // {猪猪猪=22, 朱古力=18, 猪猪侠=20}
            Integer v1 = hashMap.remove("zhuguli");
            System.out.println(v1);  // null
            Integer v2 = hashMap.remove("朱古力");
            System.out.println(v2); // 18
            System.out.println(hashMap);  // {猪猪猪=22, 猪猪侠=20}
        }
    }
    
  • public V get(Object key)根据指定的键,在Map集合中获取对应的值。

    • Map中该key不存在,则返回null
    • Map中该key存在,则返回该key对应的value
    import java.util.HashMap;
    
    public class Test03 {
        public static void main(String[] args) {
            HashMap<String,Integer> hashMap = new HashMap<>();
            hashMap.put("朱古力", 18);
            hashMap.put("猪猪侠", 20);
            hashMap.put("猪猪猪", 22);
            System.out.println(hashMap);  // {猪猪猪=22, 朱古力=18, 猪猪侠=20}
            Integer v1 = hashMap.get("zhuguli");
            System.out.println(v1);  // null
            Integer v2 = hashMap.get("朱古力");
            System.out.println(v2); // 18
            System.out.println(hashMap);  // {猪猪猪=22, 朱古力=18, 猪猪侠=20}
        }
    }
    
  • boolean containsKey(Object key)判断集合中是否包含指定的键。

    • Map中该key不存在,则返回false
    • Map中该key存在,则返回该true
    import java.util.HashMap;
    
    public class Test04 {
        public static void main(String[] args) {
            HashMap<String,Integer> hashMap = new HashMap<>();
            hashMap.put("朱古力", 18);
            hashMap.put("猪猪侠", 20);
            hashMap.put("猪猪猪", 22);
            System.out.println(hashMap);  // {猪猪猪=22, 朱古力=18, 猪猪侠=20}
            boolean v1 = hashMap.containsKey("zhuzhuzhu"); 
            System.out.println(v1);  // false
            boolean v2 = hashMap.containsKey("朱古力");
            System.out.println(v2);  // true
            System.out.println(hashMap); // {猪猪猪=22, 朱古力=18, 猪猪侠=20}
        }
    }
    

4. Map集合遍历键找值方式

  • Map集合中的方法:Set<K> keySet()返回此映射中包含的键的Set视图。
  • 步骤:
    • 使用Map集合中的方法keySet()Map集合中所有的key取出来,存储到一个Set集合中;
    • 遍历Set集合,获取Map集合中的每一个key
    • 通过Map集合中的方法get(key),找到value

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        HashMap<String,Integer> hashMap = new HashMap<>();
        hashMap.put("朱古力", 18);
        hashMap.put("猪猪侠", 20);
        hashMap.put("猪猪猪", 22);
        // 获取所有的key
        Set<String> set = hashMap.keySet();
        // 使用迭代器
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String key = it.next();
            Integer value = hashMap.get(key);
            System.out.println(key + " = " + value);
        }
        // 使用增强for循环
        for (String key : set) {
            Integer value = hashMap.get(key);
            System.out.println(key + " = " + value);
        }
    }
}

5. 使用Entry键值对对象遍历Map

  • Map集合中的方法:Set<Map.Entry<K,v>> entrySet()返回此映射中包含的映射关系的Set视图。
  • 步骤:
    • 使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中;
    • 遍历Set集合,获取每一个Entry对象;
    • 使用Entry对象中的方法getKey()getValue()获取键与值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AXpKp4De-1589461055259)(https://raw.githubusercontent.com/zhugulii/picBed/master/Map%E9%9B%86%E5%90%88%E9%81%8D%E5%8E%86%E9%94%AE%E5%80%BC%E5%AF%B9%E6%96%B9%E5%BC%8F.jpg)]

public class Test {
    public static void main(String[] args) {
        HashMap<String,Integer> hashMap = new HashMap<>();
        hashMap.put("朱古力", 18);
        hashMap.put("猪猪侠", 20);
        hashMap.put("猪猪猪", 22);
        //获取所有的entry键值对对象
        Set<Map.Entry<String, Integer>> entry = hashMap.entrySet();
        //使用迭代器
        Iterator<Map.Entry<String, Integer>> it = entry.iterator();
        while (it.hasNext()) {
            Map.Entry<String, Integer> info = it.next();
            String key = info.getKey();
            Integer value = info.getValue();
            System.out.println(key + "=" + value);
        }
        //使用增强for循环
        for (Map.Entry<String, Integer> info : entry) {
            String key = info.getKey();
            Integer value = info.getValue();
            System.out.println(key + "=" + value);
        }
    }
}

6. HashMap存储自定义类型键值

  • Map集合保证key是唯一的:作为key的元素,必须重写hashCode()方法和equals()方法。
import java.util.Objects;

public class Person {
    private String name;
    private int age;

    //覆盖重写equals方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    //覆盖重写hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    //覆盖重写toString方法
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        demo01();   //  上海-->Person{name='猪猪猪', age=22}
                    //  西安-->Person{name='巧克力', age=24}
                    //  北京-->Person{name='猪猪侠', age=20}

        demo02();   //  Person{name='猪猪猪', age=22}-->上海
                    //  Person{name='朱古力', age=18}-->杭州
                    //  Person{name='猪猪侠', age=20}-->北京
    }

    private static void demo01() {
        HashMap<String,Person> hashMap = new HashMap<>();
        hashMap.put("西安",new Person("朱古力",18));
        hashMap.put("北京",new Person("猪猪侠",20));
        hashMap.put("上海",new Person("猪猪猪",22));
        hashMap.put("西安",new Person("巧克力",24));
        //使用keySet和增强for遍历集合
        Set<String> set = hashMap.keySet();
        for(String key : set) {
            Person value = hashMap.get(key);
            System.out.println(key + "-->" + value);
        }
    }

    private static void demo02() {
        HashMap<Person,String> hashMap = new HashMap<>();
        hashMap.put(new Person("朱古力",18),"西安");
        hashMap.put(new Person("猪猪侠",20),"北京");
        hashMap.put(new Person("猪猪猪",22),"上海");
        hashMap.put(new Person("朱古力",18),"杭州");
        //使用entrySet与增强for遍历集合
        Set<Map.Entry<Person, String>> set = hashMap.entrySet();
        for (Map.Entry<Person,String> entry : set) {
            Person key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "-->" + value);
        }
    }
}

7. LinkedHashMap集合

  • java.util.LinkedHashMap<K,V> extends HashMap<K,V>
  • Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。
  • 底层原理:哈希表 + 链表(记录元素的顺序)。
import java.util.HashMap;
import java.util.LinkedHashMap;

public class Test {
    public static void main(String[] args) {
        HashMap<String,String> hashMap = new HashMap<>();
        hashMap.put("a","1");
        hashMap.put("c","2");
        hashMap.put("d","3");
        hashMap.put("b","4");
        System.out.println(hashMap);  // {a=1, b=4, c=2, d=3} 无序

        LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("a","1");
        linkedHashMap.put("c","2");
        linkedHashMap.put("d","3");
        linkedHashMap.put("b","4");
        System.out.println(linkedHashMap);  // {a=1, c=2, d=3, b=4} 有序
    }
}

8. HashTable集合

  • java.util.Hashtable<K,V>集合 implements Map<K,V>接口
  • HashMap:
    • 底层是一个哈希表,是一个线程不安全的集合,是多线程集合,速度快。
    • 可以存储null值,null键。
  • Hashtable:
    • 底层是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢。
    • 不可以存储null值,null键。
  • HashTableVector集合一样,在JDK1.2之后被更先进的集合(HashMapArrayList)取代了。
  • Hashtable的子类Properties依然活跃,且Properties集合是唯一和IO流相结合的集合。
import java.util.HashMap;
import java.util.Hashtable;

public class Test {
    public static void main(String[] args) {
        HashMap<String,String> hashMap = new HashMap<>();
        hashMap.put(null,"a");
        hashMap.put("b",null);
        hashMap.put(null,null);
        System.out.println(hashMap);  // {null=null, b=null}

        Hashtable<String,String> hashtable = new Hashtable<>();
        hashtable.put(null,"a");
        hashtable.put("b",null);
        hashtable.put(null,null);
        System.out.println(hashtable);  // 空指针异常:NullPointerException
    }
}

9. 一个小练习

//计算一个字符串中每个字符出现的次数
import java.util.HashMap;
import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        // 获取字符串
        System.out.println("请输入一个字符串:");    //  aaabbbcccabc
        Scanner sc = new Scanner(System.in);
        String str = sc.next();

        //遍历每一个字符,计算出现的次数并存入HashMap中
        HashMap<Character,Integer> hashMap = new HashMap<>();
        for(int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (!hashMap.containsKey(ch)) {
                hashMap.put(ch, 1);
            } else {
                int count = hashMap.get(ch) + 1;
                hashMap.put(ch,count);
            }
        }

        //输出
        System.out.println(hashMap);  // {a=4, b=4, c=4}
    }
}

二、JDK9对集合添加的优化

  • JDK9的新特性:
    • List接口、Set接口、Map接口,里边增加了一个静态的方法of,可以给集合一次性添加多个元素。
    • static<E> List<E> of (E...elements)
    • 使用前提:当集合中存储的元素个数已经确定了,不再改变时使用。
  • 注意:
    • of方法只适用于List接口、Set接口、Map接口,不适用于接口的实现类。
    • of方法返回值是一个不能改变的集合,集合不能再使用addput方法添加元素,会抛出异常。
    • Set接口、Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常。
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        List<Integer> list = List.of(1,2,3,4,5,6);
        System.out.println(list);  // [1, 2, 3, 4, 5, 6]
        //list.add(10);  // UnsupportedOperationException 不支持的操作异常

        Set<Integer> set = Set.of(1,2,3);
        System.out.println(set);  // [3, 2, 1]
        //set.add(4);   // UnsupportedOperationException
        //Set<Integer> set1 = Set.of(1,2,1);  // IllegalArgumentException非法参数异常

        Map<Character,Integer> map = Map.of('a',1,'b',2);
        System.out.println(map);  // {a=1, b=2}
        //map.put('c',3); // UnsupportedOperationException
        Map<Character,Integer> map1 = Map.of('a',1,'b',2,'a',3); // IllegalArgumentException
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值