在Java中,Map是一种非常重要的数据结构,它允许我们存储键值对(key-value pairs)。下面我会解释一下基本的使用方法,包括添加元素和遍历元素的方式。

Map集合的基本概念

Map接口是双列集合的一种,用于存储键值对,其中键(key)不允许重复,而值(value)可以重复。

Map的基本操作

创建Map

// 导入Map接口
import java.util.Map;

// 使用HashMap实现,这是最常见的Map实现类
import java.util.HashMap;

// 创建Map实例
Map<String, Integer> map = new HashMap<>();

添加元素

// 向Map中添加元素
map.put("张三", 25);
map.put("李四", 30);
map.put("王五", 25); // 注意,这里键是唯一的,但是值可以重复

Map集合的遍历

基本思路

遍历Map集合通常需要获取所有的键(keys),然后通过键来查找对应的值(values)。这就像通过丈夫找到妻子一样。

步骤

  1. 获取所有键的集合
  2. 遍历键的集合
  3. 根据键去找值

示例代码

// 获取所有键的集合
Set<String> keys = map.keySet();

// 遍历键的集合
for (String key : keys) {
    // 根据键去找值
    Integer value = map.get(key);
    System.out.println("Key: " + key + ", Value: " + value);
}

使用Entry Set遍历

另一种常见的遍历方式是直接获取Map中的条目集(entry set),每个条目包含了键值对。这种方式更加高效,因为它只需要遍历一次即可同时访问键和值。

示例代码

// 获取所有条目的集合
Set<Map.Entry<String, Integer>> entries = map.entrySet();

// 遍历条目的集合
for (Map.Entry<String, Integer> entry : entries) {
    String key = entry.getKey();
    Integer value = entry.getValue();
    System.out.println("Key: " + key + ", Value: " + value);
}

小结

  • Map集合主要用于存储键值对。
  • 键是唯一的,而值可以重复。
  • 遍历Map集合通常涉及获取键的集合或条目的集合,并通过键来获取对应的值。
  • 使用条目集(entry set)遍历通常更高效。

HashMap

HashMap 是 Java 中非常常用的一个实现 Map 接口的类,它提供了基于哈希表的数据结构来存储键值对。下面是对 HashMap 的详细介绍,包括其底层结构、依赖的方法以及如何自定义对象作为键。

HashMap的底层结构

HashMap 的底层是一个数组加链表或红黑树的结构。当 HashMap 的大小超过某个阈值时,链表会转换为红黑树以提高查找效率。

  • 数组HashMap 的底层是一个长度固定的数组,数组的每个位置称为一个槽(bucket)。
  • 链表/红黑树:每个槽中存放的是链表或者红黑树的根节点。如果多个键映射到同一个槽中,则它们会被组织成一个链表或者红黑树。

HashMap的工作原理

  1. 散列函数:当向 HashMap 中插入一个新的键值对时,首先计算键的散列码(通过调用键对象的 hashCode() 方法),然后根据散列码计算出该键值对应该被放入哪个槽中。
  2. 冲突解决:如果两个不同的键散列到了同一个槽中,会发生冲突。HashMap 使用链地址法来解决冲突,即在一个槽中存放一个链表或红黑树。
  3. 扩容机制:当 HashMap 的容量达到某个阈值时,它会自动扩容,通常是当前容量的两倍,并重新散列所有键值对。

HashMap依赖的方法

HashMap 的工作依赖于键对象的 hashCode()equals() 方法。

  • hashCode():每个键对象必须有一个 hashCode() 方法,该方法返回一个整数散列码,用于确定键值对在 HashMap 中的位置。
  • equals():当散列冲突发生时,HashMap 会调用键对象的 equals() 方法来判断两个键是否相等。如果两个键相等,那么它们对应的值将被更新或覆盖。

自定义对象作为键

如果你想要使用自定义的对象作为 HashMap 的键,你需要重写该对象的 hashCode()equals() 方法。

示例代码

public class Person {
    private String name;
    private int age;

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + age;
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        HashMap<Person, String> map = new HashMap<>();
        Person p1 = new Person("Alice", 25);
        Person p2 = new Person("Bob", 30);

        map.put(p1, "Developer");
        map.put(p2, "Engineer");

        System.out.println(map.get(p1)); // Developer
        System.out.println(map.get(p2)); // Engineer
    }
}

小结

  • HashMap 依赖于键的 hashCode()equals() 方法。
  • 当使用自定义对象作为键时,必须正确地重写这两个方法。
  • HashMap 的底层是数组加链表或红黑树的结构,这使得它能够高效地存储和检索键值对。
08-31 01:32