javaMap集合-HashMap-HashTable-LinkedHashMap-TreeMap

Map集合概述

概念

  • Map存储在软件包java.util包下,使用需要导包
  • interface Map<K,V>——集合的泛型,K表示Map集合中存储键的类型;V表示Map集合中存储值的类型
  • Map集合是将键映射到值的对象;不能有重复的键;每个键最多可以映射一个值
  • 有序与无序性指的是:元素存储是否按照元素的添加顺序。Map是无序的,存储结构是哈希表键值对,插入元素是根据key计算出来的哈希值来存储元素的,因此不是按照元素的添加顺序来存储对象的。

创建Map集合对象

  • 采用多态的形式 接口 对象名 = new 实现类名();
  • 具体实现类有 HashMap、LinkedHashMap、HashTable、TreeMap。
案例:验证添加相同的key,value会被覆盖

注意
当多次添加的内容具有相同的键时,会将键的内容覆盖。

// 218-
public class MapDemo {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<String, String>();

        map.put("001", "汪苏泷");
        map.put("002", "周杰伦");
        map.put("003","林俊杰");

        // 由于不允许有重复的键,所以当再添加重复键的时候,会将前者值覆盖
        map.put("001", "许嵩");

        System.out.println(map);
        // 输出:{001=汪苏泷, 002=周杰伦, 003=林俊杰}
        // 添加 许嵩后,输出:{001=许嵩, 002=周杰伦, 003=林俊杰}
    }
}

Map集合的基本功能

方法名说明
V put(K key,V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中键值对的个数
案例:测试Map集合基本方法put、remove、isEmpty、containsKey、containsValue、size、clear
// 218-
public class MapDemo1 {
    public static void main(String[] args){

        // 创建Map集合对象
        Map<String,String> map = new HashMap<String,String>();
        //添加元素 V put(K key,V value)
        map.put("杨过", "小龙女");
        map.put("郭靖","黄蓉");
        map.put("张无忌", "赵敏");

        //删除元素 V remove (Object key)
//        System.out.println(map.remove("张无忌"));
//        System.out.println(map.remove("郭襄"));
        // 返回删除key对应的value,若要删除的key不存在,则返回值是null

        // 清空集合元素
//        map.clear();
        // 输出结果是{}

        // 判断集合中键是否存在 containsKey
//        System.out.println(map.containsKey("杨过"));//true
//        System.out.println(map.containsKey("郭襄"));//false

        // 判断集合中值是否存在 containsValue
//        System.out.println(map.containsValue("小龙女"));//true
//        System.out.println(map.containsValue("小飞象"));//false

        // 判断集合中是否为空 isEmpty
//        System.out.println(map.isEmpty());//false

        // 获得集合长度
        System.out.println(map.size());// 3
        System.out.println(map);

    }
}

Map集合的获取功能

方法名说明
V get(Object key)根据键获取值
default V getOrDefault(object jet,V defaultValue)返回指定键映射到的值,如果映射不包含该键的映射,则返回defaultValue
Set < K > keySet()获取所有键的集合
Map中键是唯一的,所以返回是Set集合
Collection < V> values()获取所有值的集合
Set< Map.Entry<K,V>> entrySet()获取所有键值对 对象的集合

理解xhj:

使用 HashMap对象.get(key) 
如果key不存在于HashMap集合的时候,此表达式的返回值value为null
案例:测试get、getKeys、values、entrySet
// 218
public class MapDemo2 {
    public static void main(String[] args){
        Map<String,String> map = new HashMap<String,String>();

        map.put("夏", "夏启");
        map.put("商", "商汤");
        map.put("周","周文王姬昌");

        // 获取集合元素 get(key)
        System.out.println(map.get("夏"));
        System.out.println(map.get("秦"));
        // key键在集合中没有时,返回null

        // keySet方法 获取所有键的集合
        Set<String> set = map.keySet();
        for(String st : set){
            System.out.println(st);
        }
        // 输出 商 周 夏 不是按照存储的顺序输出

        // Value 方法 获取所有值的集合
        Collection<String> val = map.values();
        for(String st:val){
            System.out.println(st);
        }
        // 输出内容是: 商汤、周文王姬昌、夏启

//        System.out.println(map);
    }
}

Map.entry接口

概述
  • public static interface Map.Entry<K,V> Map的键值对。
  • 通过Map.entrySet方法返回的。
常用方法
方法介绍
K getKey()返回此条目对应的键
V getValue()返回此条目对应的值

HashMap

概述

底层实现:数组+链表;
可以存储null键和null值;
线程不安全;

put方法内存图

P20HashMap存储图

LinkedHashMap

概述

  • LinkedHashMap是通过 哈希表 和 链表 实现的。
  • 它是基于HashMap实现的,不同之处是定义了一个Entry header(头指针) 和 Entry tail(尾指针),不在table中,独立于table。
  • 继承了HashMap的Entry,并添加了两个属性 before 和 after,before、after、Entry header组成一个链表,实现按插入顺序或访问顺序排序。此时Entry元素保存的有:当前对象的引用、上一个元素before引用、下一个元素after的引用。
    当前对象的引用指的是 Value?
    面试3LinkedHashMap

常用方法

方法名说明
containsKey(key)查看map集合中是否有该键
set<Map.entry< K,V> entrySet()返回此map集合中包含的映射的Map

Map集合的遍历

方式1:KeySet获取键集合,for循环遍历键集合,get(key)得到值

思路
1 获取所有键的集合
	用KeySet()方法实现
2 遍历所有Key组成的集合,获取每一个Key
	使用增强for循环 
		语法for(元素数据类型 变量名:集合名)
3 根据键找对应的值
	get(Object key)方法
案例
// 218
public class MapDemo3 {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<String,String>();

        map.put("夏", "夏启");
        map.put("商", "商汤");
        map.put("周","周文王姬昌");

        // 遍历Map集合
        Set<String> set = map.keySet();
        for(String st:set){
            String sValue = map.get(st);
            System.out.println(st+", " + sValue);
        }
    }
}

方式2:entrySet获得键值对 对象的集合,for循环遍历,getKey、getValue分别得到键、值

思路
1 获取所有键值对对象的集合
	Set< Map.Entry<K,V> > entrySet() 获取所有键值对对象的集合
2 遍历键值对对象的集合,得到每一个键值对对象
	用增强for实现,得到每一个Map.Entry< K,V>
3 根据键值对对象获取键和值
	用getKey()得到键
	用getValue()得到值
案例
// 218
public class MapDemo4 {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<String,String>();

        map.put("夏", "夏启");
        map.put("商", "商汤");
        map.put("周","周文王姬昌");

        Set<Map.Entry<String, String>> entries = map.entrySet();
        for(Map.Entry<String,String> me:entries){
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key + "," + value);
        }
    }
}

方式3:keySet、迭代器对象方式,iterator,hasNext、next

import java.util.Scanner;
import java.util.*;

public class Main {
	public static void main(String[] args) {
	    
		Map<String,String> map = new HashMap<String,String>();

        map.put("夏", "夏启");
        map.put("商", "商汤");
        map.put("周","周文王姬昌");

        // 遍历Map集合
        Set<String> strSet = map.keySet();
        Iterator<String> iterator =  strSet.iterator();
        while(iterator.hasNext()){
            String skey = iterator.next();
            System.out.println(skey + ","+map.get(skey));
        }
	}
}

代码输出有问题

案例

案例1:HashMap集合存储学生对象并遍历(键-学号;值-对象)

需求:
创建一个HashMap集合,键时学号(String),值是学生对象(Student)。存储三个键值对元素,并遍历

代码:

// 218-test2
public class HashMapDemo {
    public static void main(String[] args) {

        Map<String,Student> map = new HashMap<String, Student>();

        Student s1 = new Student("汪苏泷",33);
        Student s2 = new Student("许嵩",35);
        Student s3 = new Student("徐良",38);

        map.put("001", s1);
        map.put("002", s2);
        map.put("003", s3);

        // 遍历学生集合 方式1
        Set<String> keyS = map.keySet();
        for(String s:keyS){
            Student stu = map.get(s);
            System.out.println(s + ", "+stu.getName() + ", " + stu.getAge());
        }
        System.out.println("----------------");

        // 遍历学生集合 方法2
        Set<Map.Entry<String, Student>> entries = map.entrySet();
        for(Map.Entry<String,Student> me :entries){
            String key = me.getKey();
            Student stu = me.getValue();
            System.out.println(key + ", " + stu.getName() + ",  " + stu.getAge());
        }
    }
}

案例2:HashMap集合存储学生对象并遍历(键-学生,值-居住地)

需求:
创建一个HashMap集合,键是学生对象(Student),值是居住地(String)。存储多个键值对元素,并遍历。

要求:
保证键的唯一性,如果学生对象的成员变量相同,认为是同一个对象

关键:

  • 需要在学生类中重写HashCode方法和equals方法。直接快捷键生成即可 num lock–》alt + insert
  • 重复添加键相同值不同的元素,HashMap集合认为是修改键值对元素。前提是必须重写HashCode和equals方法。

代码:

// 218-test3
public class HashMapDemo {
    public static void main(String[] args) {

        Map<Student,String> map = new HashMap<Student, String>();

        Student s1 = new Student("汪苏泷",33);
        Student s2 = new Student("许嵩",33);
        Student s3 = new Student("徐良",38);
        Student s4 = new Student("徐良",38);

        map.put(s1, "西安");
        map.put(s2, "太原");
        map.put(s3, "阳泉");
        map.put(s4, "北京");

        // 由于s3和s4的学生索引相同,则认为是同一个人,重复添加不同的地址,应该被认为是修改地址。

        Set<Student> stu = map.keySet();
        for(Student st : stu){
            System.out.println(st.getName() + ", " + st.getAge() + ", " + map.get(st));
        }
        //没有重写HashCode和equals方法时,会输出四组数据。
        // 重写之后 输出三组数据
    }
}

Student类:
public class Student {
    private String name;
    private int age;
    public Student(){}
    public Student(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;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
}

案例3:ArrayList集合存储HashMap元素并遍历

需求:
创建一个ArrayList集合,存储三个元素,每一个元素都是HashMap,每一个HashMap的键和值都是String,并遍历

// 221-test1
public class ArrayHashMapDemo {

    public static void main(String[] args) {

        ArrayList<HashMap<String,String>> array = new ArrayList<HashMap<String, String>>();

        HashMap<String,String> hm1 = new HashMap<String, String>();
        hm1.put("冯绍峰", "赵丽颖");
        hm1.put("刘恺威", "杨幂");

        array.add(hm1);

        HashMap<String,String> hm2 = new HashMap<String, String>();
        hm2.put("郭靖", "黄蓉");
        hm2.put("杨过", "小龙女");

        array.add(hm2);

        HashMap<String,String> hm3 = new HashMap<String, String>();
        hm3.put("杨绛", "我们仨");
        hm3.put("张嘉佳", "从你的全世界路过");

        array.add(hm3);

        //遍历 迭代器、简单for循环、增强for循环 采用增强for循环
        //遍历 ArrayList集合
        for(HashMap<String,String> hm:array){//元素类型 变量名:遍历集合名
            Set<String> keySet = hm.keySet();
            // 获取HashMap集合中key键组成的集合
            for(String key : keySet){
                // 增强for循环遍历key键集合
                String sValue = hm.get(key);
                // HashMap对象通过get(key)方法获取值value
                System.out.println(key + ", " + sValue);
            }
        }
    }
}

案例4:HashMap集合存储ArrayList元素并遍历

需求:
创建一个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,每一个ArrayList的元素是String,并遍历

// 221-test1
public class HashMapArrayDemo {
    /*需求:创建一个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,每一个ArrayList的元素是String,并遍历*/
    public static void main(String[] args) {
        // 创建HashMap集合
        HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();

        // 创建ArrayList对象
        ArrayList<String> arr1 = new ArrayList<String>();
        arr1.add("唐僧");
        arr1.add("猪八戒");
        ArrayList<String> arr2 = new ArrayList<String>();
        arr2.add("宋江");
        arr2.add("鲁智深");
        ArrayList<String> arr3 = new ArrayList<String>();
        arr3.add("刘备");
        arr3.add("曹操");
        // 将ArrayList对象添加到HashMap集合中
        hm.put("西游记",arr1);
        hm.put("水浒传", arr2);
        hm.put("三国演义", arr3);
        
        // 遍历HashMap集合
        Set<String> keyset = hm.keySet();
        for(String st : keyset){
            ArrayList<String> arrOne = hm.get(st);
            System.out.print(st + ", ");
            for(int i = 0 ; i < arrOne.size() ; i++){
                if(i == arrOne.size() - 1){
                    System.out.print(arrOne.get(i));
                }else{
                    System.out.print(arrOne.get(i) + ", ");
                }
            }
            System.out.println();
        }
    }
}

案例5:统计字符串中每个字符出现的次数

需求:
键盘录入一个字符串,要求统计字符串中每个字符串出现的次数

举例:
键盘录入“aababcabcdabcde” 在控制台输出:“a(5)b(4)c(3)d(2)e(1)”

分析:
	1 可以把结果看成几个部分的组成:a(5)b(4)c(3)d(2)e(1)
	2 那么每一部分又可以看成是键值对对象,键是字母,值是字母出现的次数
	3 键值对对象可以使用HashMap存储,键是字符,类型不能是char类型,而应该是其对一个的基本类型封装类Character;值是数字,也不能是int等基本数据类型,应该是其对应的封装类Integer
// 221-test1
public class ChartSumDemo {
    public static void main(String[] args) {
        /*键盘录入一个字符串,要求统计字符串中每个字符串出现的次数*/
        // 创建Scanner对象,用于获取键盘录入字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String sLine = sc.nextLine();

        // 创建HashMap集合
//        HashMap<Character,Integer> hm = new HashMap<Character, Integer>();
        // HashMap不具有排序给功能,随便输入非字母顺序的文字时,不会按照顺序输出,需要按照键排序的时候,采用TreeMap即可
        TreeMap<Character,Integer> hm = new TreeMap<Character,Integer>();

        // 遍历字符串,采用字符串.charAt
        for(int i = 0 ; i<sLine.length(); i++){
            char key = sLine.charAt(i);
            Integer value = hm.get(key);
            if(value == null){
                // 如果返回值是null,说明该键在HashMap中不存在,就把该键作为键,1作为值存储
                hm.put(key, 1);
                // 这里有一个自动装箱的操作,将char类型的key变成character类
            }else{
                // 返回值不为null 说明key存在于HashMap集合中,那么执行value++;
                value++;
                hm.put(key, value);
            }
        }

        // 遍历HashMap集合
        Set<Character> chKey = hm.keySet();
        for(Character key:chKey){
            Integer iValue = hm.get(key);
            System.out.print(key + "("+ iValue + ")" );
            // 采用输入sout 和 加号 进行拼接
        }
        System.out.println();
        System.out.println("-------------");
        
        // 采用StringBuilder进行拼接
        StringBuilder sb = new StringBuilder();

        Set<Character> chkey2 = hm.keySet();
        for(Character ckey : chkey2){
            Integer iValue = hm.get(ckey);
            sb.append(ckey).append("(").append(iValue).append(")");
        }

        String result = sb.toString();
        System.out.println(result);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值