Map与HashMap

Map是键值对集合,本课学习Map的使用。

Map接口特点

特点 说明
键值对 每个元素包含键和值
键不重复 键唯一,值可重复
无序 HashMap无序

HashMap

HashMap是最常用的Map实现。

创建HashMap

JAVA
import java.util.HashMap;
import java.util.Map;

Map<String, Integer> map1 = new HashMap<>();
Map<String, Integer> map2 = new HashMap<>(100);  // 指定容量
Map<String, Integer> map3 = new HashMap<>(map1);  // 从其他Map创建

基本操作

JAVA
import java.util.HashMap;
import java.util.Map;

public class HashMapDemo {
    public static void main(String[] args) {
        Map<String, Integer> scores = new HashMap<>();
        
        // 添加键值对
        scores.put("Alice", 95);
        scores.put("Bob", 88);
        scores.put("Charlie", 92);
        System.out.println("Map:" + scores);
        
        // 获取值
        int aliceScore = scores.get("Alice");
        System.out.println("Alice的分数:" + aliceScore);
        
        // 获取值(键不存在返回默认值)
        int davidScore = scores.getOrDefault("David", 0);
        System.out.println("David的分数:" + davidScore);
        
        // 判断
        System.out.println("是否包含Alice:" + scores.containsKey("Alice"));
        System.out.println("是否包含95:" + scores.containsValue(95));
        System.out.println("大小:" + scores.size());
        
        // 修改
        scores.put("Alice", 98);  // 覆盖旧值
        System.out.println("修改后Alice:" + scores.get("Alice"));
        
        // 删除
        scores.remove("Bob");
        System.out.println("删除后:" + scores);
    }
}

putIfAbsent

JAVA
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 95);

// 只有键不存在时才添加
map.putIfAbsent("Alice", 100);  // 不会覆盖
map.putIfAbsent("Bob", 88);     // 会添加

System.out.println(map);  // {Alice=95, Bob=88}

遍历方式

方式1:遍历keySet

JAVA
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 95);
map.put("Bob", 88);
map.put("Charlie", 92);

for (String key : map.keySet()) {
    System.out.println(key + ": " + map.get(key));
}

方式2:遍历values

JAVA
for (int value : map.values()) {
    System.out.println(value);
}

方式3:遍历entrySet

JAVA
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

方式4:Lambda

JAVA
map.forEach((key, value) -> System.out.println(key + ": " + value));

示例:Map遍历

JAVA
import java.util.HashMap;
import java.util.Map;

public class MapTraversal {
    public static void main(String[] args) {
        Map<String, Integer> scores = new HashMap<>();
        scores.put("Alice", 95);
        scores.put("Bob", 88);
        scores.put("Charlie", 92);
        
        // 遍历entrySet
        System.out.println("=== entrySet遍历 ===");
        for (Map.Entry<String, Integer> entry : scores.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
        
        // Lambda遍历
        System.out.println("=== Lambda遍历 ===");
        scores.forEach((name, score) -> 
            System.out.println(name + "的分数是" + score));
    }
}
▶ 试一试

TreeMap

TreeMap基于红黑树实现,键自动排序。

示例:TreeMap

JAVA
import java.util.Map;
import java.util.TreeMap;

public class TreeMapDemo {
    public static void main(String[] args) {
        Map<String, Integer> map = new TreeMap<>();
        map.put("Charlie", 92);
        map.put("Alice", 95);
        map.put("Bob", 88);
        
        // 按键排序
        map.forEach((key, value) -> 
            System.out.println(key + ": " + value));
        // Alice: 95
        // Bob: 88
        // Charlie: 92
    }
}
▶ 试一试

LinkedHashMap

LinkedHashMap维护插入顺序。

示例:LinkedHashMap

JAVA
import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapDemo {
    public static void main(String[] args) {
        Map<String, Integer> map = new LinkedHashMap<>();
        map.put("Charlie", 92);
        map.put("Alice", 95);
        map.put("Bob", 88);
        
        // 按插入顺序
        map.forEach((key, value) -> 
            System.out.println(key + ": " + value));
        // Charlie: 92
        // Alice: 95
        // Bob: 88
    }
}
▶ 试一试

Map常用方法

方法 说明
put(K, V) 添加键值对
get(K) 获取值
getOrDefault(K, V) 获取值,不存在返回默认值
putIfAbsent(K, V) 键不存在时添加
remove(K) 删除键值对
containsKey(K) 是否包含键
containsValue(V) 是否包含值
keySet() 所有键的Set
values() 所有值的Collection
entrySet() 所有Entry的Set
size() 大小
isEmpty() 是否为空
clear() 清空
putAll(Map) 添加所有

Map对比

特性 HashMap TreeMap LinkedHashMap
顺序 无序 排序 插入顺序
底层 哈希表 红黑树 链表+哈希表
性能 O(1) O(log n) O(1)
null键 允许1个 不允许 允许1个

示例:词频统计

JAVA
import java.util.HashMap;
import java.util.Map;

public class WordCount {
    public static Map<String, Integer> count(String text) {
        Map<String, Integer> map = new HashMap<>();
        String[] words = text.toLowerCase().split("\\s+");
        
        for (String word : words) {
            map.put(word, map.getOrDefault(word, 0) + 1);
        }
        
        return map;
    }
    
    public static void main(String[] args) {
        String text = "hello world hello java world hello";
        Map<String, Integer> counts = count(text);
        
        counts.forEach((word, count) -> 
            System.out.println(word + ": " + count));
        // hello: 3
        // world: 2
        // java: 1
    }
}

示例:分组

JAVA
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GroupBy {
    public static Map<String, List<String>> groupByFirstChar(List<String> list) {
        Map<String, List<String>> map = new HashMap<>();
        
        for (String s : list) {
            String key = s.substring(0, 1).toUpperCase();
            map.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
        }
        
        return map;
    }
    
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");
        names.add("David");
        names.add("Eve");
        
        Map<String, List<String>> groups = groupByFirstChar(names);
        groups.forEach((key, value) -> 
            System.out.println(key + ": " + value));
        // A: [Alice]
        // B: [Bob]
        // C: [Charlie]
        // D: [David]
        // E: [Eve]
    }
}

❓ 常见问题

Q HashMap的键可以是null吗?
A 可以,只能有一个null键。值可以有多个null。
Q HashMap如何判断键重复?
A 先比较hashCode,再比较equals,与HashSet类似。
Q HashMap线程安全吗?
A 不安全。多线程用ConcurrentHashMap。

📖 小节

📝 作业

  1. 词频统计: 统计字符串中每个单词出现的次数
  2. 分组: 将学生按成绩等级分组(优秀/良好/及格/不及格)
  3. 缓存: 用HashMap实现一个简单的缓存

下一课

下一课我们将学习 泛型,了解Java泛型的使用。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏