从零学Java Map集合

Java Map集合

文章目录

  • Java Map集合
    • 1 Map 结构
    • 2 Map 父接口
      • 2.1 Map接口的特点
      • 2.2 常用方法
    • 3 Map集合的实现类
      • 3.1 HashMap【重点】
      • 3.2 LinkedHashMap
      • 3.3 TreeMap
      • 3.4 Hashtable(了解)
      • 3.5 Properties 属性集合
    • 4 HashMap 源码分析

1 Map 结构

概念: 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值

从零学Java Map集合_第1张图片

2 Map 父接口

2.1 Map接口的特点

  • 用于存储键值对(Key-Value)
  • 键不可以重复,值可以重复
  • 无序无下标

2.2 常用方法

eg:

package StageOne.day19;

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

/**
 * @author 胡昊龙
 * @version 1.0
 * @description: TODO
 * @date 2024/1/12 9:14
 * Map 接口:
 * 特点: 1 存储键值对 2 键不可以重复,值可以 3 无序无下标
 */
public class TestMap {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<>();
        //1 添加
        map.put("cn","中国");
        map.put("usa","美国");
        //key 相同, 值替换
        map.put("usa","美利坚合众国");
        map.put("uk","英国");
        System.out.println("元素个数: "+map.size());
        System.out.println("打印: "+map);
        //2 删除
        //map.remove("usa");
        //System.out.println("删除后: "+map);
        //map.clear();
        //3 遍历
        //3.1 使用keySet()方法,返回只有key的Set集合
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            System.out.println(key+"..."+map.get(key));
        }
        System.out.println("----------------------");
        //3.2 使用entrySet()方法,返回映射对(既有Key,也有Value)的Set集合
        //Map.Entry 公开静态内部接口
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey()+"..."+entry.getValue());
        }
        //4 判断
        System.out.println(map.containsKey("usa"));
        System.out.println(map.containsValue("美国"));
        System.out.println(map.isEmpty());
        //5 获取value集合
        Collection<String> values = map.values();
        for (String value : values) {
            System.out.println(value);
        }
    }
}

3 Map集合的实现类

3.1 HashMap【重点】

存储结构 : 哈希表,键重复依据hashCode和equals方法。

  • JDK1.2版本,线程不安全,运行效率快
  • 允许用null 作为key或是value。

存储过程 :

  1. 根据Key 的Hash值计算位置, 如果此位置没有元素直接加入
  2. 如果此位置有元素, 则再比较Key 的equals()方法, 如果为true, 则拒绝加入, 如果为false形成来链表

eg:

package StageOne.day19;

import java.util.*;

/**
 * @author 胡昊龙
 * @version 1.0
 * @description: TODO
 * @date 2024/1/12 9:49
 */
public class TestHashMap {
    static class Student {
        String name;
        int age;

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

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", 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;
            return age == student.age && Objects.equals(name, student.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    }

    public static void main(String[] args) {
        HashMap<Student,String> hashMap = new HashMap<>();
        //1 添加
        Student s1 = new Student("小明", 18);
        Student s2 = new Student("小红", 16);
        Student s3 = new Student("小白", 20);
        //重写equals()方法和hashCode()方法
        Student s4 = new Student("小明", 18);
        hashMap.put(s1,"北京昌平");
        hashMap.put(s2,"上海浦东");
        hashMap.put(s3,"叙利亚");
        hashMap.put(s4,"乌克兰");
        System.out.println("元素个数: "+hashMap.size());
        System.out.println("打印: "+hashMap);
        //2 删除
        //hashMap.remove(s2);
        //System.out.println("删除后: "+hashMap);
        //hashMap.clear();
        //3 遍历
        //3.1 使用keySet()方法,返回只有key的Set集合
        Set<Student> keySet = hashMap.keySet();
        for (Student key : keySet) {
            System.out.println(key+"..."+hashMap.get(key));
        }
        System.out.println("----------------------");
        //3.2 使用entrySet()方法,返回映射对(既有Key,也有Value)的Set集合
        //Map.Entry 公开静态内部接口
        Set<Map.Entry<Student, String>> entries = hashMap.entrySet();
        for (Map.Entry<Student, String> entry : entries) {
            System.out.println(entry.getKey()+"..."+entry.getValue());
        }
        //4 判断
        System.out.println(hashMap.containsKey(s1));
        System.out.println(hashMap.containsValue("叙利亚"));
        System.out.println(hashMap.isEmpty());
        //5 获取value集合
        Collection<String> values = hashMap.values();
        for (String value : values) {
            System.out.println(value);
        }
    }
}

3.2 LinkedHashMap

存储结构 : 双向链表保存HashMap的顺序,有顺序的HashMap

3.3 TreeMap

存储结构 : 红黑树,重复依据排序实现。

  • 可以对key自动排序,Key需实现Comparable接口。或使用Comparator定制比较器

eg:

1 实现Comparable接口

@Override
public int compareTo(Student o) {
    int n1 = this.age-o.age;
    int n2 = this.name.compareTo(o.name);
    return n1==0?n2:n1;
}

2 定制Comparator比较器

//比较器
Comparator<Student> cmp = new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        int n1 = o1.name.compareTo(o2.name);
        int n2 = o1.age-o2.age;
        return n1==0?n2:n1;
    }
};

eg:

package StageOne.day19;

import java.util.*;

/**
 * @author 胡昊龙
 * @version 1.0
 * @description: TODO
 * @date 2024/1/12 10:21
 */
public class TestTreeMap {
    static class Student implements Comparable<Student>{
        String name;
        int age;

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

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }

        @Override
        public int compareTo(Student o) {
            int n1 = this.age-o.age;
            int n2 = this.name.compareTo(o.name);
            return n1==0?n2:n1;
        }
    }

    public static void main(String[] args) {
        //比较器
        Comparator<Student> cmp = new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int n1 = o1.name.compareTo(o2.name);
                int n2 = o1.age-o2.age;
                return n1==0?n2:n1;
            }
        };
        TreeMap<Student,String> treeMap = new TreeMap<>();
        //1 添加
        Student s1 = new Student("zzz", 18);
        Student s2 = new Student("fff", 20);
        Student s3 = new Student("aaa", 12);
        Student s4 = new Student("aaa", 12);
        treeMap.put(s1,"北极");
        treeMap.put(s2,"北京");
        treeMap.put(s3,"上海");
        System.out.println("元素个数: "+treeMap.size());
        System.out.println("打印: "+treeMap);
        //2 删除
        //treeMap.remove(s2);
        //System.out.println("删除后: "+treeMap);
        //treeMap.clear();
        //3 遍历
        //3.1 使用keySet()方法,返回只有key的Set集合
        Set<Student> keySet = treeMap.keySet();
        for (Student key : keySet) {
            System.out.println(key+"..."+treeMap.get(key));
        }
        System.out.println("----------------------");
        //3.2 使用entrySet()方法,返回映射对(既有Key,也有Value)的Set集合
        //Map.Entry 公开静态内部接口
        Set<Map.Entry<Student, String>> entries = treeMap.entrySet();
        for (Map.Entry<Student, String> entry : entries) {
            System.out.println(entry.getKey()+"..."+entry.getValue());
        }
        //4 判断
        System.out.println(treeMap.containsKey(s1));
        System.out.println(treeMap.containsValue("叙利亚"));
        System.out.println(treeMap.isEmpty());
        //5 获取value集合
        Collection<String> values = treeMap.values();
        for (String value : values) {
            System.out.println(value);
        }
    }
}

3.4 Hashtable(了解)

  • JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value。

3.5 Properties 属性集合

  • Hashtable的子类。

特点

  • 存储属性名和属性值。
  • key和value都是String,通常用于读取配置文件。
  • 没有泛型。
  • 和IO流有关系。

eg:

package StageOne.day19;

import java.util.Collection;
import java.util.Properties;
import java.util.Set;

/**
 * @author 胡昊龙
 * @version 1.0
 * @description: TODO
 * @date 2024/1/12 10:55
 * 特点:
 * 1 存储属性名和属性值
 * 2 属性名和属性值都是String类型
 * 3 没有泛型
 * 4 和IO流有关
 */
public class TestProperties {
    public static void main(String[] args) {
        //创建集合
        Properties properties = new Properties();
        //1 添加
        properties.setProperty("username","小明");
        properties.setProperty("age","20");
        properties.setProperty("gender","男");
        System.out.println("元素个数: "+properties.size());
        System.out.println("打印: "+properties);
        //2 删除
        //properties.remove("gender");
        //properties.clear();
        //3 遍历
        Set<String> strings = properties.stringPropertyNames();
        for (String key : strings) {
            System.out.println(key+"..."+properties.getProperty(key));
        }
        //4 判断
        System.out.println(properties.containsKey("username"));
        System.out.println(properties.containsValue("男"));
        //5 获取value
        Collection<Object> values = properties.values();
        for (Object value : values) {
            System.out.println(value);
        }
    }
}

4 HashMap 源码分析

  • 无参构造创建HashMap时,加载因子0.75,table是null,为了节省空间,当添加第一个元素时,table容量调整为16。
  • 当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素位置的个数。
  • jdk1.8 当每个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率。
  • jdk1.8 当红黑树节点个数小于等于6时,调整成链表。、
  • jdk1.8以前,链表是头插入,jdk1.8以后是尾插入。

你可能感兴趣的:(从零学Java,java,开发语言)