Java WeakHashMap

WeakHashMap 的键是弱引用,很适合内存敏感的场景,比如缓存。在本教程中,我们将通过示例学习 Java WeakHashMap 类及其操作。我们还将了解 WeakHashMap 和 HashMap 之间的区别。

在本教程中,我们将通过示例学习 Java WeakHashMap 类及其操作。我们还将了解 WeakHashMap 和 HashMap 之间的区别。

WeakHashMap 的键是弱引用类型(WeakReference)的,很适合内存敏感的场景,比如缓存。

如果弱引用类型的对象在程序中不再使用或者指向 null,Java 中进行垃圾回收的时候,可以立刻进行回收。本教程的后面我们会通过实例展示。

WeakHashMapHashMap 一样,实现了Map 接口

让我们先学习如何创建 WeakHashMap。然后再了解它与 HashMap 的不同之处。

创建 WeakHashMap

我们先导入 java.util.WeakHashMap 类就可以使用构造方法创建 WeakHashMap 对象了。

// 使用初始容量和负载因子构造 WeakHashMap 对象
WeakHashMap<Key, Value> numbers = new WeakHashMap<>(8, 0.6);

在上面的代码中,我们创建了一个名为 numbers 的 WeakHashMap 对象。

这里,

  • Key - Map 中键的数据类型
  • Value - Map 中值的数据类型

注意表达式 new WeakHashMap<>(8, 0.6) 。这里,第一个参数是容量,第二个参数是负载因子

  • capacity - 此 Map 的容量为 8。意思是,最开始它可以存储 8 个条目。
  • loadFactor - 此 Map 的负载因子为 0.6。这意味着每当我们的 Map 被装满 60% 时,就要扩容。

默认容量和负载系数

可以在不定义其容量和负载因子的情况下创建 WeakHashMap 。例如,

WeakHashMap<Key, Value> numbers1 = new WeakHashMap<>();

默认情况下:

  • 初始容量将为 16
  • 负载系数将为 0.75

HashMap 和 WeakHashMap 的区别

让我们先看看 WeakHashMap 的实例。

import java.util.WeakHashMap;

public class Main {
  public static void main(String[] args) {
    // Creating WeakHashMap of numbers
    WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

    String two = new String("Two");
    Integer twoValue = 2;
    String four = new String("Four");
    Integer fourValue = 4;

    // Inserting elements
    numbers.put(two, twoValue);
    numbers.put(four, fourValue);
    System.out.println("WeakHashMap: " + numbers);

    // Make the reference null
    two = null;

    // Perform garbage collection
    System.gc();

    System.out.println("WeakHashMap after garbage collection: " + numbers);
  }
}

输出

WeakHashMap: {Four=4, Two=2}
WeakHashMap after garbage collection: {Four=4}

正如我们所见,当 WeakHashMap 中的键 two 被设置为 null, 并执行垃圾收集后,键被删除。

与 HashMap 不同,WeakHashMap 的键是弱引用类型。这意味着如果不再使用该条目的键,则垃圾收集器将删除该条目。这对于节省资源很有用。

现在让我们使用 HashMap 实现的相同的示例。

import java.util.HashMap;

public class Main {
  public static void main(String[] args) {
    // Creating HashMap of even numbers
    HashMap<String, Integer> numbers = new HashMap<>();

    String two = new String("Two");
    Integer twoValue = 2;
    String four = new String("Four");
    Integer fourValue = 4;

    // Inserting elements
    numbers.put(two, twoValue);
    numbers.put(four, fourValue);
    System.out.println("HashMap: " + numbers);

    // Make the reference null
    two = null;

    // Perform garbage collection
    System.gc();

    System.out.println("HashMap after garbage collection: " + numbers);
  }
}

输出

HashMap: {Four=4, Two=2}
HashMap after garbage collection: {Four=4, Two=2}

在这里,当 HashMap 中的键 two 被设置为 null, 并执行垃圾收集后,键不会被删除。

这是因为 HashMap 的键是强引用类型。这意味着即使不再使用该条目的键,垃圾收集器也不会删除键所在的条目。

注意HashMapWeakHashMap 的所有功能都相似,只是 WeakHashMap 的键是弱引用,而 hashmap 的键是强引用。

从其他 Map 创建 WeakHashMap

以下是我们如何从其他 Map 创建 WeakHashMap。

import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

public class Main {
  public static void main(String[] args) {
    // 创建一个 HashMap 对象
    Map<String, Integer> evenNumbers = new HashMap<>();

    String two = new String("Two");
    Integer twoValue = 2;
    evenNumbers.put(two, twoValue);
    System.out.println("HashMap: " + evenNumbers);

    // 将 HashMap 转换为 WeakHashMap
    WeakHashMap<String, Integer> numbers = new WeakHashMap<>(evenNumbers);

    System.out.println("WeakHashMap: " + numbers);
  }
}

输出

HashMap: {Two=2}
WeakHashMap: {Two=2}

WeakHashMap 的方法

WeakHashMap 类实现了 Map 接口定义的所有操作。

向 WeakHashMap 插入元素

  • put() - 将指定的键值对条目插入到 Map 中
  • putAll() - 将指定 Map 中的所有条目插入到此 Map 中
  • putIfAbsent() - 如果 Map 中不存在指定的键,则将指定的键值对条目插入到 Map 中

例如,

import java.util.WeakHashMap;

public class Main {
  public static void main(String[] args) {
    // Creating WeakHashMap of even numbers
    WeakHashMap<String, Integer> evenNumbers = new WeakHashMap<>();

    String two = new String("Two");
    Integer twoValue = 2;

    evenNumbers.put(two, twoValue);

    String four = new String("Four");
    Integer fourValue = 4;

    evenNumbers.putIfAbsent(four, fourValue);
    System.out.println("WeakHashMap of even numbers: " + evenNumbers);

    WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

    String one = new String("One");
    Integer oneValue = 1;
    numbers.put(one, oneValue);

    numbers.putAll(evenNumbers);
    System.out.println("WeakHashMap of numbers: " + numbers);
  }
}

输出

WeakHashMap of even numbers: {Four=4, Two=2}
WeakHashMap of numbers: {Two=2, Four=4, One=1}

entrySet()、keySet() 和 values()

  • entrySet() - 返回 Map 的所有键值对条目的 Set 集合
  • keySet() - 返回 Map 的所有键组成的 Set 集合
  • values() - 返回 Map 的所有值组成的集合

例如,

import java.util.WeakHashMap;

public class Main {
  public static void main(String[] args) {
    // Creating WeakHashMap of even numbers
    WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

    String one = new String("One");
    Integer oneValue = 1;
    numbers.put(one, oneValue);

    String two = new String("Two");
    Integer twoValue = 2;
    numbers.put(two, twoValue);

    System.out.println("WeakHashMap: " + numbers);

    System.out.println("Key/Value mappings: " + numbers.entrySet());
    System.out.println("Keys: " + numbers.keySet());
    System.out.println("Values: " + numbers.values());
  }
}

输出

Key/Value mappings: [Two=2, One=1]
Keys: [Two, One]
Values: [2, 1]

get() 和 getOrDefault()

  • get() - 返回与指定键关联的值。 如果未找到键,则返回 null
  • getOrDefault() - 返回与指定键关联的值。如果未找到键,则返回指定的默认值。

例如,

import java.util.WeakHashMap;

public class Main {
  public static void main(String[] args) {
    WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

    String one = new String("One");
    Integer oneValue = 1;
    numbers.put(one, oneValue);

    String two = new String("Two");
    Integer twoValue = 2;
    numbers.put(two, twoValue);

    System.out.println("WeakHashMap: " + numbers);

    int value1 = numbers.get("Two");
    System.out.println("Using get(): " + value1);

    int value2 = numbers.getOrDefault("Four", 4);
    System.out.println("Using getOrDefault(): " + value2);
  }
}

输出

WeakHashMap: {Two=2, One=1}
Using get(): 2
Using getOrDefault(): 4

移除 WeakHashMap 元素

  • remove(key) - 删除并返回与指定键关联的条目
  • remove(key, value) - 删除与指定键和指定值匹配的条目,成功返回 true,否则返回 false

例如,

import java.util.WeakHashMap;

public class Main {
  public static void main(String[] args) {
    // Creating WeakHashMap of even numbers
    WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

    String one = new String("One");
    Integer oneValue = 1;
    numbers.put(one, oneValue);

    String two = new String("Two");
    Integer twoValue = 2;
    numbers.put(two, twoValue);

    System.out.println("WeakHashMap: " + numbers);

    int value = numbers.remove("Two");
    System.out.println("Removed value: " + value);

    boolean result = numbers.remove("One", 3);
    System.out.println("Is the entry {One=3} removed? " + result);

    System.out.println("Updated WeakHashMap: " + numbers);
  }
}

输出

WeakHashMap: {Two=2, One=1}
Removed value: 2
Is the entry {One=3} removed? false
Updated WeakHashMap: {One=1}

WeakHashMap 的其他方法

  • clear(): 从 Map 中删除所有条目
  • containsKey(): 检查 Map 是否包含指定的键
  • containsValue(): 检查 Map 是否包含指定的值
  • size(): 返回 Map 的大小
  • isEmpty(): 检查 Map 是否为空