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

Java Map集合的用法(非常详细)

在 Java 开发中,Map 集合的使用也是比较广泛的。Map 集合以键值对方式存储数据,键和值一一对应,通过键可以获取值,并且键不能重复。

Map 接口的常用实现类有 HashMap、TreeMap、Properties,本节将详细讲解 Map 接口的使用。

Java Map接口简介

Map 接口与 Collection 接口是并列存在的,它以键值对(key-value)的形式存储元素,可以按照键访问值。

Map 集合本身由键(key)的集合和值(value)的集合构成:
这里给出 Map 接口的常用方法,如下表所示:

表:Map 接口的常用方法
方法 方法描述
Object put(Object key, Object value) 以键值对的方式向集合添加数据
Object remove(Object key) 以键为参数删除集合中的键值对数据
void putAll(Map t) 将其他 Map 中的数据添加到当前 Map 集合中
void clear() 清除当前 Map 中的所有数据
Object get(Object key) 根据键获取对应的值,找不到则返回 null
boolean containsKey(Object key) 判断集合中是否包含对应的键,包含则返回 true
boolean containsValue(Object value) 判断集合中是否包含对应的值,包含则返回 true
int size() 返回集合中的记录数
boolean isEmpty() 判断集合是否为空的,空则返回 true
Set keySet() 返回集合中键的 Set 视图
Collection values() 返回集合中值的 Collection 视图
Set entrySet() 返回集合中的键值对的 Set 视图

Java HashMap集合

HashMap 类是 Map 接口中使用最多的实现类,它的键和值允许为 null。因为它的键也是使用哈希算法进行存储的,所以与 HashSet 集合一样,不保证数据的顺序,另外键也不允许重复。

HashMap 判断两个键是否相同的规则与 HashSet 类似,也是先通过 hashCode() 方法判断键的哈希值是否相同,再通过 equals() 方法判断键的数据是否相等。

HashMap 内部结构和数据存储过程如下图所示:


图 1 HashMap 内部结构和数据存储过程

根据图 1 所示,HashMap 的内部结构是由数组和链表构成的。当向 HashMap 中添加键值对数据时,会先使用键的 hashCode() 方法得到一个哈希值。这个哈希值对应一个集合中的存储位置:
接下来,通过案例来演示 HashMap 集合的使用:
import java.util.*;

public class Demo {
    public static void main(String[] args) {
        Map map = new HashMap(); // 创建HashMap集合
        map.put(null, null); // 存入键值对,键和值都为null
        map.put("car1", "布加迪"); // 存入非空数据
        map.put("car2", "保时捷");
        map.put("car3", "兰博基尼");
        System.out.println(map.size()); // 打印集合长度
        System.out.println(map); // 打印集合所有元素
        System.out.println(map.get("car3")); // 取出并打印键为car3的值
    }
}
程序的运行结果如下:

4
{null=null, car2=保时捷, car3=兰博基尼, car1=布加迪}
兰博基尼

以上程序输出了 HashMap 集合的长度和集合中的元素,并将键为 car3 的值打印输出。

HashMap 中的键是不可重复的,因为键是用 Set 集合存储的。接下来,通过案例来演示 HashMap 的键重复时的情况:
import java.util.*;

public class Demo {
    public static void main(String[] args) { // 创建HashMap集合
        Map map = new HashMap(); // 存入元素
        map.put("car1", "布加迪");
        map.put("car2", "保时捷");
        map.put("car3", "兰博基尼");
        map.put("car3", "劳斯莱斯"); // 存入重复的键car3
        System.out.println(map); // 打印集合所有元素
    }
}
程序的运行结果如下:

{car2=保时捷, car3=劳斯莱斯, car1=布加迪}

以上代码中,键“car3”被添加了两次,第 1 次“car3”值为“兰博基尼”,第 2 次“car3”值为“劳斯莱斯”,当键被重复添加时,后添加的键值覆盖了前面添加的键值。

Java TreeMap集合

TreeMap 类也是 Map 接口的一个常用的实现类。TreeMap 集合存储键值对时,会根据键进行排序。该集合可以保证所有的键值对都处于有序状态。

接下来,通过案例来演示 TreeMap 集合的具体用法:
import java.util.*;

public class Demo {
    public static void main(String[] args) {
        Map map = new TreeMap(); // 创建TreeMap集合
        map.put("Girl3", "西施"); // 添加元素
        map.put("Girl2", "王昭君");
        map.put("Girl1", "貂蝉");
        map.put("Girl4", "杨玉环");
        Iterator iterator = map.keySet().iterator(); // 获取迭代器对象
        while (iterator.hasNext()) {
            Object key = iterator.next(); // 取到键
            Object value = map.get(key); // 取到值
            System.out.println(key + ":" + value);
        }
    }
}
程序的运行结果如下:

Girl1:貂蝉
Girl2:王昭君
Girl3:西施
Girl4:杨玉环

程序中先创建 TreeMap 集合对象,接着添加键为“Girl3”、值为“西施”的元素,后添加键为“Girl2”、值为“王昭君”的元素和键为“Girl1”、值为“貂蝉”的元素,最后添加了键为“Girl4”、值为“杨玉环”的元素。

运行之后,结果中可以看到集合中元素顺序并不是这样,而是按键值的大小来升序排列的,这是因为 String 实现了 Comparable 接口,所以默认会按照自然顺序进行排序。

TreeMap 除了可以使用自然顺序进行排序外,还支持定制排序,可以根据自己的需求实现排序逻辑。接下来,通过案例来演示在 TreeMap 集合中实现定制排序:
import java.util.*;

public class Demo {
    public static void main(String[] args) {
        // 创建TreeMap集合并传入一个实现了Comparator接口的自定义对象
        Map map = new TreeMap(new TestComparator()); // 添加元素
        map.put("Girl3", "西施");
        map.put("Girl2", "王昭君");
        map.put("Girl1", "貂蝉");
        map.put("Girl4", "杨玉环");
        // 获取迭代器对象
        Iterator iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            Object key = iterator.next(); // 取到键
            Object value = map.get(key); // 取到值
            System.out.println(key + ":" + value);
        }
    }
}

class TestComparator implements Comparator { // 自定义类,实现Comparator接口
    public int compare(Object o1,Object o2) {
        // 将Object类型参数强转为String类型
        String s1 = (String) o1;
        String s2 = (String) o2;
        return s2.compareTo(s1); // 返回比较之后的值
    }
}
程序的运行结果如下:
Girl4:杨玉环
Girl3:西施
Girl2:王昭君
Girl1:貂蝉
程序中是按照键为 Girl3、Girl2、Girl1、Girl4 的顺序,将元素存入集合的,运行结果中显示元素是按降序排列的,这是因为本例自定义的 TestComparator 类实现的 compare(Object o1, Object o2)方法重写了排序逻辑,这就是 TreeMap 集合的定制排序。

Java Properties集合

Hashtable 是 Map 接口中一个早期的并且线程安全的实现类。与 HashMap 类似的是,Hashtable 存储的键值对数据也是无序的,它判断键是否相等的方式与 HashMap 类是相同的。但是,与 HashMap 不同的是,它的键和值都不允许使用 null。

Hashtable 类因为要确保线程安全,所以存取元素速度比较慢,目前用的比较少。不过它的子类 Properties 在实际开发中用的比较多,该子类对象主要用于处理 properties 属性文件,由于属性文件里的键和值都是字符串类型,所以 Properties 集合里的键和值都是字符串类型。

这里给出 Properties 类的常用方法,如下表所示:

表:Properties 类的常用方法
方法 方法描述
String getProperty(String key) 根据键获取值
String getProperty(String key, String defaultValue) 根据 key 获取对应的值。如果值不存在,则直接将 defaultValue 作为返回值
Object setProperty(String key, String value) 以键值对的方式设置数据。如果键存在,则覆盖之前的数据;如果键不存在,则添加数据
void load(InputStream inStream) 通过输入流从属性文件中加载键值对数据,加载到的键值对数据添加到 Properties 里
void store(OutputStream out, String s) 通过输出流将 Properties 中的键值对输出到指定文件

接下来,通过案例来演示 Properties 类的用法:
import java.io.FileOutputStream;
import java.util.Properties;

public class Demo {
    public static void main(String[] args) throws Exception {
        // 创建Properties集合类对象
        Properties pro = new Properties();
        // 向Properties集合中添加键值对数据
        pro.setProperty("username", "AAA");
        pro.setProperty("password", "123456");
        // 将Properties集合中的属性保存到当前项目根目录下程序自动创建的data.ini文件中
        pro.store(new FileOutputStream("data.ini"), "title");
    }
}
上面程序运行后,会在项目根目录下生成一个名为 data.ini 的文件,文件内容如下:

#title
#Wed Jan 13 19:19:44 CST 2021
password=123456
username=AAA

相关文章