具有不区分大小写键的Java Map

2023/06/07

1. 概述

Map是Java中最常见的数据结构之一,而String是Map键最常见的类型之一。默认情况下,此类Map的键区分大小写

在这个简短的教程中,我们将探索不同的Map实现,这些实现接受String的所有大小写变体作为相同的key

2. 使用不区分大小写的键

让我们更详细地检查我们试图解决的问题。

假设我们有一个包含一个条目的Map<String, Integer>:

让我们添加下一个条目:

map.put("ABC", 2);

使用区分大小写键的Map时,我们最终会得到两个条目:

但是当使用不区分大小写键的Map时,内容将是:

在接下来的示例中,我们将深入研究一些流行的Map实现的不区分大小写的实现:TreeMap、HashMap和LinkedHashMap。

3. TreeMap

TreeMap是NavigableMap的一个实现,这意味着它总是在插入后根据给定的Comparator对条目进行排序。此外,TreeMap使用Comparator来查找插入的键是重复键还是新键。

因此,如果我们提供一个不区分大小写的String Comparator,我们将得到一个不区分大小写的TreeMap

幸运的是,String已经提供了这个静态Comparator:

public static final Comparator <String> CASE_INSENSITIVE_ORDER

我们可以在构造函数中提供:

Map<String, Integer> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
treeMap.put("abc", 1);
treeMap.put("ABC", 2);

现在,当我们运行测试时,我们可以看到Map的大小为1:

assertEquals(1, treeMap.size());

并将值更新为2:

assertEquals(2, treeMap.get("aBc").intValue());
assertEquals(2, treeMap.get("ABc").intValue());

现在让我们使用相同的String删除条目,但使用另一种情况:

treeMap.remove("aBC");
assertEquals(0, treeMap.size());

我们应该记住,与提供O(1)插入和查找的HashMap相比,TreeMap的put和get等函数平均花费O(logn)的时间

还值得注意的是,TreeMap不允许空键。

4. Apache的CaseInsensitiveMap

Apache的Commons-Collections是一个非常流行的Java库,提供了大量有用的类,其中就有CaseInsensitiveMap

CaseInsensitiveMap是一个基于哈希的Map,它在添加或检索键之前将键转换为小写。与TreeMap不同,CaseInsensitiveMap允许空键插入。

首先,我们需要添加commons-collections4依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>

现在,我们可以使用CaseInsensitiveMap并添加两个条目:

Map<String, Integer> commonsHashMap = new CaseInsensitiveMap<>();
commonsHashMap.put("abc", 1);
commonsHashMap.put("ABC", 2);

当我们测试它时,我们期望得到与之前看到的相同的结果:

assertEquals(1, commonsHashMap.size());
assertEquals(2, commonsHashMap.get("aBc").intValue());
assertEquals(2, commonsHashMap.get("ABc").intValue());

commonsHashMap.remove("aBC");
assertEquals(0, commonsHashMap.size());

5. Spring的LinkedCaseInsensitiveMap

Spring Core是一个Spring Framework模块,它还提供实用程序类,包括LinkedCaseInsensitiveMap。

LinkedCaseInsensitiveMap包装了一个LinkedHashMap,它是一个基于哈希表和链表的Map。与LinkedHashMap不同,它不允许空键插入。LinkedCaseInsensitiveMap保留原始顺序以及键的原始大小写,同时允许在任何情况下调用get和remove等函数

首先,让我们添加spring-core依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.2.5.RELEASE</version>
</dependency>

现在,我们可以初始化一个新的LinkedCaseInsensitiveMap:

Map<String, Integer> linkedHashMap = new LinkedCaseInsensitiveMap<>();
linkedHashMap.put("abc", 1);
linkedHashMap.put("ABC", 2);

添加测试它:

assertEquals(1, linkedHashMap.size());
assertEquals(2, linkedHashMap.get("aBc").intValue());
assertEquals(2, linkedHashMap.get("ABc").intValue());

linkedHashMap.remove("aBC");
assertEquals(0, linkedHashMap.size());

6. 总结

在本教程中,我们研究了使用不区分大小写的键创建Java Map的不同方法,并使用了不同的类来实现这一点。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章