Java Map With Case-Insensitive Keys – 带有区分大小写的键的Java地图

最后修改: 2020年 4月 13日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Map is one of the most common data structures in Java, and String is one of the most common types for a map’s key. By default, a map of this sort has case-sensitive keys.

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

In this short tutorial, we’ll explore different Map implementations that accept all case variations of a String as the same key.

在这个简短的教程中,我们将探索不同的Map 实现,接受String 的所有情况变化作为同一个键

2. A Closer Look at Map with Case-Insensitive Keys

2.仔细观察带有区分大小写的键的Map

Let’s examine the problem we’re trying to solve in more detail.

让我们更详细地研究一下我们要解决的问题。

Suppose we have a Map<String, Integer>  with one entry:

假设我们有一个Map<String, Integer> ,有一个条目。

Let’s add the next entry:

让我们添加下一个条目。

map.put("ABC", 2);

When working with a Map with case-sensitive keys, we’ll end up with two entries:

当使用带有大小写敏感键的Map时,我们最终会有两个条目。

But when working with a Map with case-insensitive keys, the content will be:

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

In the next examples, we’ll dive into case-insensitive implementations of some popular Map implementations: TreeMap, HashMap, and LinkedHashMap.

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

3. TreeMap

3.树状图

TreeMap is an implementation of NavigableMap, which means that it always sorts the entries after inserting, based on a given Comparator. Also, TreeMap uses a Comparator to find if an inserted key is a duplicate or a new one.

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

Therefore, if we provide a case-insensitive String Comparator, we’ll get a case-insensitive TreeMap.

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

Luckily, String already supplies this static Comparator:

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

public static final Comparator <String> CASE_INSENSITIVE_ORDER

which we can supply in the constructor:

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

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

And now, when we run tests, we can see that the size of the Map is one:

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

assertEquals(1, treeMap.size());

and the value is updated to 2:

并将该值更新为2。

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

Now let’s remove the entry, using the same String, but with another case:

现在让我们删除这个条目,使用同样的String,但有另一种情况。

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

We should keep in mind that functions like put and get cost an average time of O(log n) for the TreeMap compared to a HashMap that provides O(1) insertion and lookup.

我们应该记住,putget这样的函数对TreeMap来说,平均花费了O(log n)的时间,而HashMap则提供O(1)的插入和查询。

It is also worth noting that TreeMap doesn’t allow null keys.

同样值得注意的是,TreeMap不允许null键。

4. Apache’s CaseInsensitiveMap

4.Apache的CaseInsensitiveMap

Apache’s Commons-Collections is a very popular Java library, providing a large number of useful classes with CaseInsensitiveMap among them.

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

CaseInsensitiveMap is a hash-based Map, which converts keys to lower case before they are being added or retrieved. Unlike TreeMap, CaseInsensitiveMap allows null key inserting.

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

First, we need to add the commons-collections4 dependency:

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

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

Now, we can use CaseInsensitiveMap and add two entries:

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

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

When we test it, we expect the same results as we saw previously:

当我们测试它时,我们期待的结果与我们之前看到的一样。

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’s LinkedCaseInsensitiveMap

5.Spring的LinkedCaseInsensitiveMap

Spring Core is a Spring Framework module that also provides utility classes, including LinkedCaseInsensitiveMap.

Spring Core是一个Spring框架模块,它也提供了一些实用类,包括LinkedCaseInsensitiveMap

LinkedCaseInsensitiveMap wraps a LinkedHashMap, which is a Map based on a hash table and a linked list. Unlike LinkedHashMap, it doesn’t allow null key inserting. LinkedCaseInsensitiveMap preserves the original order as well as the original casing of keys while allowing calling functions like get and remove with any case.

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

First, let’s add the spring-core dependency:

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

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

Now, we can initialize a new LinkedCaseInsensitiveMap:

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

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

add test it:

添加测试它。

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

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

6. Conclusion

6.结语

In this tutorial, we’ve looked at different ways to create a Java Map with case-insensitive keys and used different classes to obtain this.

在本教程中,我们研究了创建具有不区分大小写键的Java Map的不同方法,并使用不同的类来获得这种效果。

As always, the code is available over on GitHub.

像往常一样,代码可在GitHub上获得