Map接口详解

本文详细介绍了Java中的Map接口,包括其层次结构、常用方法,以及HashMap、TreeMap、LinkedHashMap、ConcurrentHashMap、IdentityHashMap和WeakHashMap的特点。此外,还探讨了SortedMap接口及其方法,通过示例展示了如何使用这些Map实现类和接口。
摘要由CSDN通过智能技术生成

Map接口

Map 接口是 Java 集合框架中用于表示键值对的数据结构接口。它提供了一种通过键来查找值的方式,并且键和值都可以是任意的 Java 对象。

Map接口的层次结构

Java中的Map接口定义了映射(key-value对)的通用接口,并提供了常用的操作方法,例如添加、删除、更新和查询元素等。Map接口的实现类可以存储任意类型的键值对,并允许根据key快速查找value。

Map接口层次结构如下:

java.lang.Object
    └─ java.util.AbstractMap<K,V>
        ├─ java.util.HashMap<K,V>
        ├─ java.util.LinkedHashMap<K,V>
        ├─ java.util.TreeMap<K,V>
        ├─ java.util.ConcurrentHashMap<K,V>
        ├─ java.util.WeakHashMap<K,V>
        └─ java.util.IdentityHashMap<K,V>

其中,AbstractMap是一个抽象类,提供了一些通用的方法实现,HashMap是基于哈希表实现的Map,LinkedHashMap是基于链表的Map,TreeMap是基于红黑树实现的Map,ConcurrentHashMap是线程安全的Map,WeakHashMap是使用弱引用的Map,IdentityHashMap是使用对象引用相等判断key的Map。

除了这些标准的实现类之外,用户也可以自定义Map实现类,只需要实现Map接口并提供相应的实现即可。

Map常用方法
方法名说明
put(K key, V value)向 Map 中添加一个键值对
get(Object key)根据键返回对应的值,如果键不存在则返回 null
remove(Object key)根据键从 Map 中移除对应的键值对
containsKey(Object key)判断 Map 中是否包含指定的键
containsValue(Object value)判断 Map 中是否包含指定的值
size()返回 Map 中键值对的数量
isEmpty()判断 Map 是否为空
keySet()返回 Map 中所有键的集合
values()返回 Map 中所有值的集合
entrySet()返回 Map 中所有键值对的集合

其中,put() 方法用于向 Map 中添加键值对,如果已经存在相同的键,则会覆盖原来的值。get() 方法用于根据键查找对应的值,如果键不存在则返回 nullremove() 方法用于根据键从 Map 中移除对应的键值对,如果键不存在则不做任何操作。containsKey() 方法用于判断 Map 中是否包含指定的键,返回 truefalsecontainsValue() 方法用于判断 Map 中是否包含指定的值,返回 truefalsesize() 方法返回 Map 中键值对的数量。isEmpty() 方法用于判断 Map 是否为空。keySet() 方法返回 Map 中所有键的集合,values() 方法返回 Map 中所有值的集合,entrySet() 方法返回 Map 中所有键值对的集合。

HashMap和TreeMap的区别
  • HashMap是基于哈希表实现的Map,其内部结构为数组和链表的组合。其中数组用来存储元素,链表则用来解决哈希冲突。HashMap的键不保证有序。在进行元素的遍历时,其顺序是不确定的。
  • TreeMap是基于红黑树实现的Map,其内部结构为平衡二叉树。TreeMap的键是有序的,可以根据键来实现排序。
  • 当需要快速添加、删除元素并且不需要关心元素的顺序时,可以选择HashMap;当需要按照键进行排序时,可以选择TreeMap。
LinkedHashMap的特点

LinkedHashMap是基于链表的Map,其内部结构除了具有HashMap的基本结构外,还维护了一个双向链表来记录元素的顺序。LinkedHashMap的键可以按照插入顺序或者访问顺序进行排序。在进行元素的遍历时,其顺序与元素的排序顺序一致。

ConcurrentHashMap的特点

ConcurrentHashMap是线程安全的Map,其内部结构为分段锁的哈希表,可以支持多个线程同时对Map进行操作。它的操作效率比Hashtable要高,因为它只对部分数据进行加锁,不同的线程可以同时访问不同的段,从而提高了并发度。与Hashtable不同的是,ConcurrentHashMap不支持null键和null值。

IdentityHashMap的特点

IdentityHashMap是使用对象引用相等判断key的Map,与使用equals()方法判断相等不同。在IdentityHashMap中,只有当两个key的引用相等时,它们才被视为相等。因此,IdentityHashMap可以用于解决使用对象引用作为键的情况。

WeakHashMap的特点

WeakHashMap是使用弱引用的Map。在WeakHashMap中,如果某个键不再被其它对象引用,那么该键所对应的键值对将被自动删除。WeakHashMap通常用于缓存数据,以避免内存泄漏的问题。

示例代码
示例1:使用 HashMap 实现的 Map 集合对象
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo {
    public static void main(String[] args) {
        // 创建 Map 对象
        Map<String, String> map = new HashMap<>();

        // 添加键值对
        map.put("name", "张三");
        map.put("age", "20");
        map.put("gender", "男");

        // 获取键值对
        String name = map.get("name");
        System.out.println("name: " + name);

        // 移除键值对
        map.remove("age");

        // 判断键是否存在
        boolean containsKey = map.containsKey("gender");
        System.out.println("containsKey: " + containsKey);

        // 判断值是否存在
        boolean containsValue = map.containsValue("女");
        System.out.println("containsValue: " + containsValue);

        // 获取键的集合
        Set<String> keySet = map.keySet();
        System.out.println("keySet: " + keySet);

        // 获取值的集合
        Set<String> valueSet = (Set<String>) map.values();
        System.out.println("valueSet: " + valueSet);

        // 获取键值对的集合
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        for (Map.Entry<String, String> entry : entrySet) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        // 判断 Map 是否为空
        boolean isEmpty = map.isEmpty();
        System.out.println("isEmpty: " + isEmpty);

        // 获取 Map 的大小
        int size = map.size();
        System.out.println("size: " + size);
    }
}

这个示例代码中,使用 HashMap 实现了一个 Map 对象,添加了多个键值对。然后,通过 get() 方法获取指定键的值,通过 remove() 方法移除指定键的键值对。还使用了 containsKey()containsValue() 方法判断键和值是否存在于 Map 中。通过 keySet()values() 方法获取键和值的集合,使用 entrySet() 方法获取键值对的集合,并遍历输出了所有的键值对。最后,使用 isEmpty() 方法判断 Map 是否为空,使用 size() 方法获取 Map 的大小。

SortedMap的定义

SortedMap 接口继承自 Map 接口,表示一组有序的键值对。其中的键按照升序排列,可以通过键的范围进行导航。SortedMap 接口提供了根据键的范围来获取子映射、获取第一个和最后一个键等方法,同时也提供了各种与 Map 接口相同的方法,如 put、get、containsKey、containsValue 等。

SortedMap 接口中常用的方法
方法名描述
Comparator<? super K> comparator()返回用来对键进行排序的比较器,如果键实现了 Comparable 接口,可以使用自然顺序进行排序
SortedMap<K, V> subMap(K fromKey, K toKey)返回从 fromKeytoKey 范围内的子映射,不包括 toKey
SortedMap<K, V> headMap(K toKey)返回从开始到 toKey 范围内的子映射,不包括 toKey
SortedMap<K, V> tailMap(K fromKey)返回从 fromKey 到结束范围内的子映射,包括 fromKey
K firstKey()返回第一个键
K lastKey()返回最后一个键

SortedMap 接口的实现类包括 TreeMap,它使用红黑树(一种自平衡的二叉查找树)来存储键值对,因此键是有序的。

示例代码
示例1:使用 SortedMap 接口的实现类 TreeMap 来创建并操作有序映射
import java.util.*;

public class SortedMapDemo {
    public static void main(String[] args) {
        // 创建 SortedMap 对象
        SortedMap<String, String> sortedMap = new TreeMap<>();

        // 添加键值对
        sortedMap.put("1", "one");
        sortedMap.put("2", "two");
        sortedMap.put("3", "three");
        sortedMap.put("4", "four");

        // 获取值
        String value1 = sortedMap.get("1");
        System.out.println("Value of key '1': " + value1);

        // 获取子映射
        SortedMap<String, String> subMap = sortedMap.subMap("2", "4");
        System.out.println("Sub map from '2' to '4': " + subMap);

        // 获取第一个和最后一个键
        String firstKey = sortedMap.firstKey();
        String lastKey = sortedMap.lastKey();
        System.out.println("First key: " + firstKey);
        System.out.println("Last key: " + lastKey);

        // 遍历键值对
        for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
        }

        // 删除键值对
        sortedMap.remove("3");

        // 判断是否包含键或值
        boolean containsKey = sortedMap.containsKey("3");
        boolean containsValue = sortedMap.containsValue("four");
        System.out.println("Contains key '3': " + containsKey);
        System.out.println("Contains value 'four': " + containsValue);
    }
}

该示例代码首先创建了一个 TreeMap 对象 sortedMap,并向其中添加了一些键值对。然后使用 get 方法获取键为 "1" 的值,使用 subMap 方法获取键的范围在 "2""4" 之间的子映射,使用 firstKeylastKey 方法获取第一个和最后一个键。接下来使用 entrySet 方法遍历键值对,使用 remove 方法删除键为 "3" 的键值对,并使用 containsKeycontainsValue 方法判断是否包含键或值。

示例2:使用 Comparable 接口实现SortedMap的key的排序

import java.util.SortedMap;
import java.util.TreeMap;

public class SortedMapExample {
    public static void main(String[] args) {
        // 创建 SortedMap 对象,使用默认排序方式(基于 key 的自然排序)
        SortedMap<Integer, String> map = new TreeMap<>();
        map.put(5, "Five");
        map.put(3, "Three");
        map.put(2, "Two");
        map.put(4, "Four");
        map.put(1, "One");

        // 打印出排序后的元素
        for (Integer key : map.keySet()) {
            System.out.println(key + " : " + map.get(key));
        }
    }
}
示例3:使用 Comparator接口(比较器)实现SortedMap的key的排序
import java.util.Comparator;
import java.util.SortedMap;
import java.util.TreeMap;

public class SortedMapExample {
    public static void main(String[] args) {
        // 创建 SortedMap 对象,使用指定比较器实现排序
        SortedMap<Integer, String> map = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1); // 基于 key 的逆序排序
            }
        });
        map.put(5, "Five");
        map.put(3, "Three");
        map.put(2, "Two");
        map.put(4, "Four");
        map.put(1, "One");

        // 打印出排序后的元素
        for (Integer key : map.keySet()) {
            System.out.println(key + ": " + map.get(key));
        }
    }
}
示例4:基于 Comparable 接口和比较器(Comparator)实现排序
import java.util.*;

public class SortedMapDemo {

    public static void main(String[] args) {
        // 基于 Comparable 接口实现排序的 SortedMap
        SortedMap<Person, String> personMap = new TreeMap<>();
        personMap.put(new Person("Tom", 18), "Tom is 18 years old.");
        personMap.put(new Person("Alice", 20), "Alice is 20 years old.");
        personMap.put(new Person("Bob", 19), "Bob is 19 years old.");

        for (Person key : personMap.keySet()) {
            System.out.println(key + " - " + personMap.get(key));
        }

        // 基于 Comparator 实现排序的 SortedMap
        SortedMap<Person, String> personMap2 = new TreeMap<>(new PersonComparator());
        personMap2.put(new Person("Tom", 18), "Tom is 18 years old.");
        personMap2.put(new Person("Alice", 20), "Alice is 20 years old.");
        personMap2.put(new Person("Bob", 19), "Bob is 19 years old.");

        for (Person key : personMap2.keySet()) {
            System.out.println(key + " - " + personMap2.get(key));
        }
    }

    // Person 类实现 Comparable 接口
    static class Person implements Comparable<Person> {
        private String name;
        private int age;

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

        @Override
        public String toString() {
            return name + "(" + age + ")";
        }

        @Override
        public int compareTo(Person o) {
            // 先按照年龄排序,如果年龄相同则按照姓名排序
            if (this.age != o.age) {
                return this.age - o.age;
            } else {
                return this.name.compareTo(o.name);
            }
        }
    }

    // 比较器实现类
    static class PersonComparator implements Comparator<Person> {
        @Override
        public int compare(Person o1, Person o2) {
            // 先按照年龄排序,如果年龄相同则按照姓名排序
            if (o1.age != o2.age) {
                return o1.age - o2.age;
            } else {
                return o1.name.compareTo(o2.name);
            }
        }
    }
}

在这个示例中,我们定义了一个 Person 类,该类实现了 Comparable 接口,用于基于对象的自然顺序进行排序。我们同时也定义了一个比较器 PersonComparator,用于在创建 SortedMap 对象时指定比较器,实现基于比较器的排序。

这个示例中,我们分别创建了两个 SortedMap 对象,一个基于 Person 对象的自然顺序进行排序,另一个则是基于 PersonComparator 比较器实现排序。在输出时,我们遍历 SortedMap 的 key 集合,可以看到输出的 key 都是按照排序规则排好序的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

参果

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值