0
点赞
收藏
分享

微信扫一扫

【Java笔记】集合Map接口的使用

目录

Map接口的架构

Map结构的理解

Map接口的底层实现原理

HashMap的底层实现原理

JDK 7.0 及之前

JDK 8.0 及之后

HashMap源码中需要了解的常量

LinkedHashMap的底层实现原理

Map接口的常用方法

TreeMap的使用

Properties的使用


Map接口的架构

Map 接口:双列集合,用来存储一对(key - value)的数据(映射)

        HashMap:作为 Map 的主要实现类,线程不安全但效率高。可以储存 null 的 key 和 value

                LinkedHashMap:保证在遍历 map 元素时,可以按照添加的顺序实现遍历。                                                 LinkedHashMap 在原有的 HashMap 底层结构基础上,添加了一对                                                 指针,指向前一个和后一个元素。对于频繁的遍历操作,此类执行                                                        效率高于 HashMap

        TreeMap:保证按照添加的 key - value 对进行排序,实现排序遍历。此时考虑 key 的自然排                             序或定制排序

        Hashtable:作为 Map 接口古老的实现类,线程安全但效率低。不能存储 null 的 key 和 value

                Properties:常用来处理配置文件。key 和 value 都是 String 类型

   

Map结构的理解

1. Map 中的 key:无序的、不可重复的,使用 Set 存储所有的 key。其中 key 所在的类要重写            equals()和 hashCode()(以 HashMap 为例)

2. Map 中的 value:无序的,可重复的,使用 Collection 存储所有的 value。其中 value 所在类要      重写 equals()

3.  一个键值对 key - value 构成了一个 Entry 对象

4. Map 中的 Entry:无序的、不可重复的,使用 Set 存储所有的 Entry

Map接口的底层实现原理

HashMap的底层实现原理

JDK 7.0 及之前

HashMap map = new HashMap ( );

在实例化以后,底层创建了长度是 16 的一维数组 Entry [ ] table

在不断添加数据的过程中,会涉及到扩容的问题,当超出临界值(且要存放的位置非空)时,扩容。默认的扩容方式:扩容为原来容量的 2 倍,并将原有的数据复制过来

map . put (key1 , value1);

首先,调用 key1 所在类的 hashCode()计算 key1 的哈希值,此哈希值经过某种算法计算以后,得到在 Entry 数组中的存放位置

        如果此位置上的数组为空,此时的 key1 - value1 添加成功

        如果此位置上的数组不为空,(意味着此位置上存在一个或多个数据(以链表的形式存                  在)),比较 key1 和已经存在的一个或多个数据的哈希值

                如果 key1 的哈希值与已经存在的数据的哈希值都不同,此时 key1 - value1 添加成功

                如果 key1 的哈希值与已经存在的某一个数据(key2 - value2)的哈希值相同,比较                        key1 所在类的 equals(key2)

                         如果 equals()返回 false,此时 key1 - value1添加成功

                         如果 equals()返回 true,此时使用 value1 替换 value2

关于添加成功的后两种情况,此时的 key1 - value1 和原来的数据以链表方式存储

JDK 8.0 及之后

相较于 JDK 7.0 底层实现方面的不同

1. new HashMap ( ):底层没有创建一个长度为 16 的数组

2. JDK 8.0 底层的数组是 Node [ ] ,而非 Entry [ ]

3. 首次调用 put()方法时,底层创建长度为 16 的数组

4. JDK 7.0 底层结构只有数组 + 链表,JDK 8.0 中底层结构为数组 + 链表 + 红黑树

    当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64 ,此      时此索引位置上的所有数据改为使用红黑树存储

import org.junit.Test;
import java.util.HashMap;
import java.util.Map;

public class HashMapTest {
    @Test
    public void test(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put(45,1234);
        map.put("CC",56);
        System.out.println(map);
    }
}

>>> {AA=123, CC=56, 45=1234}

HashMap源码中需要了解的常量

DEFAULT_INITIAL_CAPACITY:HashMap 的默认容量,16

DEFAULT_LOAD_FACTOR:HashMap 的默认加载因子,0.75

threshold:扩容的临界值,容量 * 填充因子,16 * 0.75 = 12

TREEIFY_THRESHOLD:Bucket 中链表长度大于该默认值,转化为红黑树,8

MIN_TREEIFY_CAPACITY:桶中的 Node 被树化时最小的 hash 表容量,64

LinkedHashMap的底层实现原理

static class Entry <K, V> extends HashMap . Node <K, V> {

        Entry <K, V> before, after; // 能够记录添加的元素的先后顺序

        Entry (int hash, K key, V value, Node <K, V> next) {

                super (hash, key, value, next);

        }

}

import org.junit.Test;
import java.util.LinkedHashMap;
import java.util.Map;

public class MapTest {
    @Test
    public void test(){
        Map map = new LinkedHashMap();
        map.put("AA",123);
        map.put(45,1234);
        map.put("CC",56);
        System.out.println(map);
    }
}

>>> {AA=123, 45=1234, CC=56}

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 org.junit.Test;
import java.util.*;

public class MapTest {
    @Test
    public void test(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put(45,1234);
        map.put("CC",56);
        //putAll()
        Map map1 = new HashMap();
        map1.put("BB",123);
        map1.put("DD",567);
        map.putAll(map1);
        System.out.println("putAll():" + map);
        //remove()
        Object value = map.remove("CC");
        System.out.println("remove():" + map);
        //get()
        System.out.println("get():" + map.get(45));
        //containsKey()
        boolean isExist = map.containsKey("BB");
        System.out.println("containsKey():" + isExist);
        //keySet()
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //values()
        Collection values = map.values();
        for (Object obj : values){
            System.out.println(obj);
        }
        //entrySet()
        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while (iterator1.hasNext()){
            Object obj = iterator1.next();
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "---->" + entry.getValue());
        }
        //clear
        map.clear();
    }
}

>>> putAll():{AA=123, CC=56, BB=123, DD=567, 45=1234}
    remove():{AA=123, BB=123, DD=567, 45=1234}
    get():1234
    containsKey():true
    AA
    BB
    DD
    45
    123
    123
    567
    1234
    AA---->123
    BB---->123
    DD---->567
    45---->1234

TreeMap的使用

向 TreeMap 中添加 key - value,要求 key 必须是由同一个类创建的对象

要按照 key 进行排序,分为:自然排序和定制排序

使用原理与 TreeSet 相同,详细请见下面文章中 TreeSet 的使用方法,如何重写 compareTo()与 compare()

Collection子接口:Set接口:https://blog.csdn.net/lijibai_/article/details/124060677

Properties的使用

Properties 类是 Hashtable 的子类,该类对象用于处理属性文件

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertiesTest {
    public static void main(String[] args) throws IOException {
        Properties pros = new Properties();
        FileInputStream fis = new FileInputStream("db.properties");
        pros.load(fis);
        String name = pros.getProperty("name");
        String password = pros.getProperty("password");
        System.out.println("name = " + name + "," + "password = " + password);
    }
}
举报

相关推荐

0 条评论