CodeGym /Java 博客 /China /HashMap:这是哪种映射?
作者
Milan Vucic
Programming Tutor at Codementor.io

HashMap:这是哪种映射?

已在 China 群组中发布
你好!在本课中,我们将对 Java HashMap 这个知识点进行深入复习。之前,我们研究了数据结构,即元数据本身所存储的地方。在数组或 ArrayList/LinkedList 中,我们存储了一些元素。但如果我们的任务稍加改变该如何呢? 假想下列任务:创建一个包含 100 人的列表,存储每个人的姓名和护照号码。原理上这并不难。例如,你可以将两者都填充到一个字符串中,然后创建下列字符串的列表:
"艾米莉亚 阿基拉, 4211 717171"。
但该解决方案有两个缺点。首先,我们可能需能按护照号码进行搜索。鉴于这种信息存储格式,这种搜索会有问题。 其次,我们可以轻而易举地使用相同的护照号码创建两个不同的人。这是该解决方案最严重的缺点。这种情况绝对不允许:两个人的护照号码是相同的。 我们可以使用一种新数据结构:映射。这种数据结构称为“关联数组”,但是这个术语很少使用。我们常将其称为“字典”或“映射”。:) 该数据结构与我们之前考虑的数据结构有什么根本不同吗? 最重要一项事实是,Map 中的数据以键值对的方式存储。任何事情都可以用键和值表示:数字、字符串或其他类的对象。 今天,我们将学习 Map 类的常见实现:Java HashMapHashMap:这是哪种映射?- 2

那么,关于 Java 中的 HashMap,我们需要了解些什么?

创建起来非常轻松:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();
}
在这里,我们创建了一个字典,将元素以“数字-字符串”对的形式存储。数字将作为键,字符串作为值。我们还指定键类型 (Integer) 和值类型 (String)。 为什么? 首先,HashMap 键始终是唯一的。这非常适合我们使用,因为可以将护照号码用作键,从而避免重复出现。值将是一个带有全名的字符串(不同的人可以有相同的名字;我们不考虑这种情况)。 将一个新对添加到 HashMap,如下所示:

public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put (212133, "Bridget Logan");
       passportsAndNames.put (162348, "Ivan the Great");
       passportsAndNames.put(8082771, "Donald John Trump");
       System.out.println(passportsAndNames);
   }
}
为此,我们使用方法 put()。此外,HashMap 重写了 toString() 方法,因此可以在控制台上显示。输出如下所示:
{212133=布里奇特·洛根, 8082771=唐纳德·特朗普, 162348=伊万很棒}
现在让我们验证键是否真的是唯一的? 我们尝试使用已在映射中使用的键添加一个新元素:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");
   passportsAndNames.put(162348, "Albert Kent");// This key has already been used
   System.out.println(passportsAndNames);
}
输出:
{212133=布里奇特·洛根, 8082771=唐纳德·特朗普, 162348=阿尔伯特·肯特}
如你所见,与键 162348 关联的先前值已被覆盖。 我们使用术语“键”是有原因的。HashMap 中的值是使用键访问的,反之则不行。无法使用值获取键,因为值可能不是唯一的。 从 HashMap 获取或删除元素时可以清楚地看到这一点:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   String lidiaName = passportsAndNames.get(212133);
   System.out.println(lidiaName);

   passportsAndNames.remove(162348);
   System.out.println(passportsAndNames);
}
要从字典中获取一个值或删除一个对,我们必须将与该值对应的唯一键传递给 get()remove()。与数组和列表不同,Java 中的 HashMap 没有数字下标:值是使用键访问的。 控制台输出:
布里奇特·洛根 {212133=布里奇特·洛根, 8082771=唐纳德·特朗普}
ArrayListLinkedList 类可用于检查列表是否包含任何特定元素。 Java HashMap 可以做此工作。更重要的是,我们可以为该对的两个成员执行此操作:这就是 containsKey()(检查键)和 containsValue()(检查值)方法的用途。

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.containsKey(11111));
   System.out.println(passportsAndNames.containsValue("Donald John Trump"));
}
输出:
false true
Java 中 HashMap 的另一个方便特性是,你可以获得所有键和所有值的单独列表。 这可以通过 keySet()values() 方法来实现。

public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put (212133, "Bridget Logan");
       passportsAndNames.put (162348, "Ivan the Great");
       passportsAndNames.put(8082771, "Donald John Trump");

       Set keys = passportsAndNames.keySet();
       System.out.println("Keys: " + keys);

       ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
       System.out.println("Values: " + values);
   }
}
HashMap:这是哪种映射? - 2键被提取到一个 Set 中,这个知识点我们还没涉及。它的特殊之处在于不能包含重复的元素。现在最重要的是要记住,所有键的列表都可以从 HashMap 中检索到单独的集合中。 在示例中,我们将值保存到普通的 ArrayList 中。 控制台输出:
键:[212133, 8082771, 162348] 值:[布里奇特·洛根, 唐纳德·特朗普, 伊万很棒]
size()clear() 方法的作用与我们之前讨论过的结构完全相同:第一个方法返回字典中当前元素的编号,第二个方法删除所有元素。

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.size());
   passportsAndNames.clear();
   System.out.println(passportsAndNames);
}
输出:
3 {}
要检查我们的 HashMap 中是否至少有一个元素,我们可以使用 isEmpty() 方法:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   if (!passportsAndNames.isEmpty()) {

       System.out.println(passportsAndNames);
   }
}
输出:
{212133=布里奇特·洛根, 8082771=唐纳德·特朗普, 162348=伊万很棒}
现在我们只会在初步检查后输出到控制台。:) 另一个有趣的地方是两个 Map 可以合并为一个 Map 。这是使用 putAll() 方法完成的。我们在第一个 HashMap 上调用它,将第二个 HashMap 作为参数传递,然后将第二个中的元素添加到第一个即可:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();
   HashMap<Integer, String> passportsAndNames2 = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   passportsAndNames2.put(917352, "Clifford Patrick");
   passportsAndNames2.put(925648, "Mitchell Salgado");

   passportsAndNames.putAll(passportsAndNames2);
   System.out.println(passportsAndNames);
}
输出:
{917352=克利福德·帕特里克, 212133=布里奇特·洛根, 8082771=唐纳德·特朗普, 925648=米切尔·萨尔加多, 162348=伊万很棒}
passportsAndNames2 中的所有对已复制到 passportsAndNames。 现在考虑一个更复杂的例子。具体而言,即时在循环中迭代 HashMap

for (Map.Entry<Integer, String> entry: passportsAndNames.entrySet()) {
   System.out.println(entry);
}
Map.Entry 类表示字典中的键值对。entrySet() 方法返回 HashMap 中所有对的列表。因为我们的映射由这些 Map.Entry 对组成,所以我们迭代的是对,而不是单独的键或值。 输出:
212133=布里奇特·洛根 8082771=唐纳德·特朗普 162348=伊万很棒
另外,不要忘记研究 HashMap 的官方 Oracle 文档。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION