1. 概述
在本教程中,我们将讨论如何在不知道键的情况下从 HashMap 中获取第一个键值对。
我们会先使用迭代器(Iterator)的方式获取第一个元素,然后介绍通过 Java Stream API 的方式。最后,我们会探讨 HashMap 在获取“第一个”元素时可能带来的问题,并给出解决方案。
2. 使用 Iterator 获取第一个键值对
假设我们有如下一个 *HashMap<Integer, String>*:
Map<Integer, String> hashMap = new HashMap<>();
hashMap.put(5, "A");
hashMap.put(1, "B");
hashMap.put(2, "C");
我们可以借助 Iterator 来获取第一个 entry。具体做法是获取 entrySet 的迭代器,然后调用 next()
方法拿到第一个 entry:
Iterator<Map.Entry<Integer, String>> iterator = hashMap.entrySet().iterator();
Map.Entry<Integer, String> actualValue = iterator.next();
Map.Entry<Integer, String> expectedValue = new AbstractMap.SimpleEntry<Integer, String>(1, "B");
assertEquals(expectedValue, actualValue);
⚠️ 注意:这里返回的“第一个”entry 并不是我们插入的第一个(即 5=A),而是 HashMap 内部结构决定的顺序。
3. 使用 Java Stream 获取第一个键值对
另一种方式是使用 Java Stream API。我们可以对 entrySet 创建一个流,并调用 findFirst()
方法来获取第一个元素:
Map.Entry<Integer, String> actualValue = hashMap.entrySet()
.stream()
.findFirst()
.get();
然后进行断言验证:
Map.Entry<Integer, String> expectedValue = new AbstractMap.SimpleEntry<Integer, String>(1, "B");
assertEquals(expectedValue, actualValue);
✅ 这种方式代码更简洁,语义也更清晰,适合在函数式编程风格中使用。
4. 插入顺序问题
还记得我们是怎么构造这个 hashMap 的吗?
hashMap.put(5, "A");
hashMap.put(1, "B");
hashMap.put(2, "C");
我们是按 5 → 1 → 2 的顺序插入的,但如果我们打印一下这个 map:
System.out.println(hashMap);
输出可能是:
{1=B, 2=C, 5=A}
❌ HashMap 并不保证插入顺序。
如果我们再插入一个元素:
hashMap.put(0, "D");
Iterator<Map.Entry<Integer, String>> iterator = hashMap.entrySet().iterator();
Map.Entry<Integer, String> actualValue = iterator.next();
Map.Entry<Integer, String> expectedValue = new AbstractMap.SimpleEntry<Integer, String>(0, "D");
assertEquals(expectedValue, actualValue);
会发现“第一个”元素又变了,变成了 0=D
。这再次印证了 HashMap 的无序性。
解决方案:使用 LinkedHashMap
如果我们要保留插入顺序,应该使用 *LinkedHashMap*:
Map<Integer, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put(5, "A");
linkedHashMap.put(1, "B");
linkedHashMap.put(2, "C");
linkedHashMap.put(0, "D");
Iterator<Map.Entry<Integer, String>> iterator = linkedHashMap.entrySet().iterator();
Map.Entry<Integer, String> actualValue = iterator.next();
Map.Entry<Integer, String> expectedValue = new AbstractMap.SimpleEntry<Integer, String>(5, "A");
assertEquals(expectedValue, actualValue);
✅ 这样我们就能确保获取的是真正按插入顺序的第一个 entry。
5. 总结
本文介绍了从 HashMap 中获取第一个键值对的几种方式:
- 使用 Iterator
- 使用 Java Stream API
但最重要的一点是:
❌ HashMap 不保证插入顺序
✅ 如果你需要保留插入顺序,请使用 LinkedHashMap
完整代码示例可以在 GitHub 上找到。