三种工具的介绍
1)Hashtable
-
是一个古老的实现,随 Java 1.0 引入。
-
它是同步的,这意味着它是线程安全的,但这也意味着它通常比非同步的实现(如 HashMap )慢。
-
不允许使用 null 键或 null 值。
-
是一个基于散列表的 Map 实现。
2)HashMap
-
是 Java 1.2引入的,作为 Hashtable 的一个更先进的替代品。
-
它是非同步的,这意味着它不是线程安全的,但其性能在单线程环境下通常比 Hashtable 好。
-
允许一个 null 键和多个 null 值。
-
同样是基于散列的 Map 实现,但提供更快的迭代。
3)TreeMap
-
基于红黑树( Red-Black tree )的 NavigableMap 实现。
-
按照键的自然顺序或创建时提供的 Comparator 进行排序,因此它除了作为 Map 外,还可以用作双端队列。
-
不是线程安全的。
-
不允许 null 键(如果使用自然排序),但允许多个 null 值。
-
提供了一些特殊的方法来处理键的有序性,如
firstKey()
,lastKey()
,headMap()
,tailMap()
等。
简单示例
Hashtable 示例
//在这个 Hashtable 示例中,尝试将 null 作为键或值添加到映射中会抛出 NullPointerException
public class HashtableExample {
public static void main(String[] args) {
Map<String, Integer> numbers = new Hashtable<>();
numbers.put("One", 1);
numbers.put("Two", 2);
// numbers.put(null, 3); // 这会抛出 NullPointerException
// numbers.put("Four", null); // 这也会抛出 NullPointerException
System.out.println("Hashtable: " + numbers);
}
}
HashMap 示例
//在 HashMap 示例中,我们可以看到它允许使用 null 作为键和值,这与 Hashtable 不同
public class HashMapExample {
public static void main(String[] args) {
Map<String, Integer> numbers = new HashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put(null, 3); // HashMap 允许 null 键
numbers.put("Four", null); // HashMap 也允许 null 值
System.out.println("HashMap: " + numbers);
}
}
TreeMap 示例
//尝试向 TreeMap 中添加一个 null 键,这将导致抛出 NullPointerException,因为 TreeMap 在自然排序模式下无法处理 null 键。然而,向 TreeMap 添加 null 值是允许的,我们可以看到 Cherry 对应的值被成功添加为 null**/
public class TreeMapExample {
public static void main(String[] args) {
// 创建一个 TreeMap 实例
TreeMap<String, Integer> treeMap = new TreeMap<>();
// 添加几个非空键和值
treeMap.put("Apple", 1);
treeMap.put("Banana", 2);
// 尝试添加 null 值 - 这是允许的
treeMap.put("Cherry", null);
// 打印 TreeMap
System.out.println(treeMap);
try {
// 尝试添加 null 键 - 这会抛出 NullPointerException
treeMap.put(null, 3);
} catch (NullPointerException e) {
System.out.println("Cannot insert null key into a TreeMap when using natural ordering.");
}
}
}
加深记忆的例子
1)Hashtable:可以比喻为一辆老式火车,它的运行是非常稳定和可靠的,因为它采用了同步措施,确保了每一个操作都是安全的。不过,正因为其老旧和同步的特性,它在速度和效率上不如现代化的交通工具,特别是在需要快速发展的现代应用场景中。
2)HashMap:则可以看作是一辆私家车,它在日常使用中提供了极大的便利性和效率。私家车不需要像火车一样严格的时刻表和运行轨迹,你可以随意驾驶到任何地方,就像 HashMap 允许用户灵活地存取数据。但是,如果没有适当的同步机制,在并发环境中使用私家车( HashMap )可能会导致数据的不一致,就像多个司机试图同时驾驶同一辆车可能会引起混乱一样。
3)TreeMap:可以想象成是一辆按照预定路线运行的观光巴士,这辆巴士按照固定的路径和时刻表运行,确保旅客可以按照既定的顺序访问各个景点。这就像 TreeMap 保持键值对按照特定的顺序(通常是自然排序)排列一样。虽然这种有序性在寻找和遍历数据时非常有用,但是因为需要维护这个顺序,它在数据插入和删除时可能比 HashMap 这样的私家车更慢一些。
其他补充
Hashtable
-使用场景
-
当需要确保数据的线程安全,且在多线程环境中共享 Map 时,可以考虑使用 Hashtable。
-
由于其性能相对较低,推荐在遗留代码中或者特定要求线程安全的小规模数据集合中使用。
HashMap
-使用场景
-
在非多线程环境中,或者在读多写少的场景下(可以通过外部同步来解决线程安全问题),HashMap 是一个优选,因为它提供了更好的性能。
-
当需要快速查找、插入和删除键值对时,特别是在数据量较大的情况下。
TreeMap
-使用场景
-
当需要一个总是保持排序状态的 Map 时,TreeMap 是最合适的选择。它适用于需要频繁地进行有序遍历或范围搜索的场景。
-
在需要根据键进行排序的应用中,如时间线索引、自然排序的目录结构等。
-
当数据结构的大小频繁变动,且需要保持有序状态时,TreeMap 通常比维护一个 ArrayList 之后再排序要高效。