首页 > 编程笔记 > Java笔记 阅读:9

Java Map集合类(HashMap和TreeMap)用法详解

Java 中的 Map 是一种双列集合,Map 的每个元素都包含一个键对象 Key 和一个值对象 Value,键对象和值对象之间存在对应关系,这种关系称为映射。

Map 中的映射关系是一对一的,一个键只能映射一个值,但允许多个不同的键映射到同一个值上。键对象 Key 必须是唯一的,不允许重复,值对象 Value 允许重复。

Map 是实现映射集合的根接口。Map 定义了关于映射集合的相关的操作方法,常用方法如下表所示。

表 1 Map 的常用方法
方法声明 功能描述
void clear() 删除集合中的所有元素
boolean containsKey(Object key) 查询集合中是否存在指定的 key
boolean containsValue(Object value) 查询集合中是否存在指定的 value
Set<Map.Entry<K,V>> entrySet() 返回集合中包含的映射的 Set 集合视图
boolean equals(Object o) 比较指定的对象与此集合对象是否相等
V get(Object key) 返回指定键所映射的值,若此映射不包含该键的映射关系,则返回 null
boolean isEmpty() 判断集合是否为空
Set<K> keySet() 返回集合中包含的所有键的 Set 集合视图
V put(K key, V value) 添加一个键值对,若存在该键,则替换原有的值
void putAll(Map<? extends K,? extends V> m) 将集合 m 的所有键值对复制到当前集合中
V remove(Object key) 删除指定键对应的键值对
default V replace(K key, V value) 将集合中指定键对象 key 映射的值修改为 value
int size() 返回集合中键值对的个数
Collection<V> values() 返回集合中包含的所有值的集合视图

Map 的具体实现类主要有两个:HashMap 和 TreeMap。与实现 Set 的两个类相似,如果在 Map 中插入、删除和定位元素,那么 HashMap 类是最好的选择。但如果要按顺序遍历键,那么 TreeMap 类是最好的选择。

Java HashMap类

定义 HashMap 类的语法格式如下:
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
HashMap 类是基于哈希表实现的 Map 接口定义的。HashMap 类允许使用 null 键和 null 值。

HashMap 类的构造方法有 4 个,如下表所示。

表 2 HashMap 类的构造方法
方法声明 功能描述
HashMap() 构造一个空的 HashMap,具有默认的初始容量(16)和负载因子(0.75)
HashMap(int initialCapacity) 构造一个空的 HashMap,具有指定的初始容量和默认的负载因子(0.75)
HashMap(int initialCapacity, float loadFactor) 构造一个空的 HashMap,具有指定的初始容量和负载因子
HashMap(Mapm) 构造一个映射关系与指定 Map 相同的新的 HashMap

【实例】HashMap 类的基本应用。
import java.util.HashMap;
import java.util.Map;

public class Demo{
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        Integer num = map.put("语文", 99);
        // 因为之前没有“语文”键,所以 put() 方法的返回值为 null
        System.out.println(num);
        map.put("数学", 80);
        num = map.put("语文", 90);
        // 已经存在“语文”键,此时 put() 方法的返回值为原来的值,即 99
        System.out.println(num);
        map.put("物理", 75);
        map.put("英语", 82);
        System.out.println(map);
        System.out.println("----------------");
        num = map.get("物理");
        System.out.println(num);
        num = map.get("化学");
        // 不存在“化学”键,返回值为 null
        System.out.println(num);
        System.out.println("----------------");
        num = map.remove("语文");
        System.out.println(num);
        System.out.println(map);
    }
}
运行结果为:

null
99
{语文=90, 数学=80, 物理=75, 英语=82}
75
null
90
{数学=80, 物理=75, 英语=82}

值得注意的是,在 Java 中,TreeMap 的 put() 方法的 key 值若不存在,则返回值是 null;若 key 值存在,则返回原先被替换的 value 值。

【实例】HashMap 类的遍历的应用。
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class Demo{
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("语文", 95);
        map.put("数学", 98);
        map.put("英语", 70);
        map.put("物理", 75);
        map.put("化学", 82);
        System.out.println(map);
        /* 遍历所有 Key
         * Set<K> keySet()
         * 获得保存当前所有 Key 的 Set 集合
         */
        // Set<String> keySet = map.keySet();
        for (String key : map.keySet()) {
            System.out.println(key + ":" + map.get(key));
        }
        /*
         * 遍历所有 Value
         * Collection<V> values()
         * 获得保存所有 Value 的集合
         */
        // Collection<Integer> values = map.values();
        for (Integer score : map.values()) {
            System.out.println(score);
        }
        /* 遍历键值对
         * Set<Entry> entrySet()
         * java.util.Map.Entry 每个对象表示 Map 集合中的一组键值对
         */
        // Set<Entry<String, Integer>> entry = map.entrySet();
        for (Entry<String, Integer> e : map.entrySet()) {
            String key = e.getKey();
            Integer value = e.getValue();
            System.out.println(key + ":" + value);
        }
    }
}
运行结果为:

{物理=75, 数学=98,化学=82, 语文=95, 英语=70}
物理:75
数学:98
化学:82
语文:95
英语:70
75
98
82
95
70
物理:75
数学:98
化学:82
语文:95
英语:70

值得注意的是,如果想要遍历 Map 中全部的键值对,那么建议使用 entrySet() 方法。使用 entrySet() 方法可以一次性查询出所有的键值对信息,效率较高。如果先使用 keySet() 方法查询出所有键,再使用键从 Map 中查询对应的值,就会产生多个基于键进行搜索的过程,从而造成不必要的资源消耗。

Jva TreeMap类

定义 TreeMap 类的语法格式如下:
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, Serializable
TreeMap 类是对基于红黑树(Red-Black tree)的 NavigableMap 接口的具体实现。该集合根据键的自然顺序进行排序,或者根据构造集合对象时提供的 Comparator 进行排序。

TreeMap 类的构造方法和其他常用方法如下表所示。

表 3 TreeMap类的构造方法和其他常用方法
方法声明 功能描述
TreeMap() 使用其键的自然排序构造一个新的、空的 TreeMap
TreeMap(Comparator<? super K> comparator) 构造一个新的、空的 TreeMap,按照给定的比较器排序
TreeMap(Map<? extends K,? extends V> m) 构造一个新的 TreeMap,其中包含与给定 Map 类的对象 m 相同的映射,根据其键的自然顺序进行排序
Map.Entry<K,V> ceilingEntry(K key) 返回一个大于或等于给定键的最小键值对。若不存在,则返回 null
K ceilingKey(K key) 返回一个大于或等于给定键的最小键值对。若不存在,则返回 null
NavigableSet<K> descendingKeySet() 返回此集合中所有键的逆序集合视图
Map.Entry<K,V> firstEntry() 返回此集合中最小的键值对。若集合为空,则返回 null
K firstKey() 返回此集合中的第一个(最小)键
V get(Object key) 返回指定键所映射的值。若不存在,则返回 null
Set<K> keySet() 返回此集合中所有键的 Set 视图
Map.Entry<K,V> lastEntry() 返回此集合中最大键的键值对。若为空,则返回 null
Map.Entry<K,V> pollFirstEntry() 移除并返回此集合中最小键的键值对。若为空,则返回 null
Map.Entry<K,V> pollLastEntry() 移除并返回此集合中最大键的键值对。若为空,则返回 null

【实例】使用 TreeMap 类保存电话簿中的姓名和电话号码,并按照姓名排序输出。
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class Demo{
    public static void main(String[] args) {
        // 创建 TreeMap 集合对象
        TreeMap<String, String> telephonelist = new TreeMap<>();
        // 添加 4 个键值对
        telephonelist.put("zhang san", "13566568721");
        telephonelist.put("li si", "15566254221");
        telephonelist.put("wang wu", "13166257821");
        telephonelist.put("liu liu", "13747258571");
        Set<Map.Entry<String, String>> mylist = telephonelist.entrySet();
        System.out.println("我的电话簿:");
        for (Map.Entry t : mylist) {
            System.out.printf("姓名:%-5s; 电话号码:%s\n", t.getKey(), t.getValue());
        }
    }
}
运行结果为:

我的电话簿:
姓名:li si    ; 电话号码:15566254221
姓名:liu liu  ; 电话号码:13747258571
姓名:wang wu ; 电话号码:13166257821
姓名:zhang san; 电话号码:13566568721

由运行结果可知,当把集合元素添加到 TreeMap 集合中时,自动对键按照字典的顺序进行排序。

相关文章