1. Overview
1.概述
In this tutorial, we’ll learn how to construct a map with primitive keys and values.
在本教程中,我们将学习如何用原始键和值构造一个地图。
As we know, the core Java Maps don’t allow the storage of primitive keys or values. That’s why we’ll introduce some external third-party libraries that provide primitive map implementations.
正如我们所知,核心的Java Maps不允许存储原始键或值。这就是为什么我们要引入一些外部的第三方库来提供原始的地图实现。
2. Eclipse Collections
2.Eclipse Collections
Eclipse Collections is a high-performance collection framework for Java. It provides improved implementations as well as some additional data structures, including several primitive collections.
Eclipse Collections是一个用于Java的高性能集合框架。它提供了改进的实现以及一些额外的数据结构,包括几个原始的集合。
2.1. Mutable and Immutable Maps
2.1.可变和不可变的地图
Let’s create an empty map where both keys and values are primitive ints. For that, we’ll use the IntIntMaps factory class:
让我们创建一个空的地图,其中键和值都是原始的ints。为此,我们将使用IntIntMaps工厂类。
MutableIntIntMap mutableIntIntMap = IntIntMaps.mutable.empty();
The IntIntMaps factory class is the most convenient way to create primitive maps. It allows us to create both mutable and immutable instances of the desired type of map. In our example, we created the mutable instance of IntIntMap. Similarly, we can create an immutable instance by simply replacing the IntIntMaps.mutable static factory call with IntIntMaps.immutable:
IntIntMaps工厂类是创建原始地图的最便捷方式。它允许我们创建所需类型的地图的可变和不可变实例。在我们的例子中,我们创建了IntMap的可变实例。同样地,我们可以通过简单地将IntMaps.mutable静态工厂调用替换为IntMaps.immutable来创建一个不可变的实例。
ImmutableIntIntMap immutableIntIntMap = IntIntMaps.immutable.empty();
So, let’s add a key, value pair to our mutable map:
所以,让我们给我们的可变地图添加一个键,值对。
mutableIntIntMap.addToValue(1, 1);
Likewise, we can create mixed maps with reference and primitive type key-value pairs. Let’s create a map with String keys and double values:
同样,我们可以用引用和原始类型的键值对创建混合地图。让我们创建一个键值为String、值为double的地图。
MutableObjectDoubleMap dObject = ObjectDoubleMaps.mutable.empty();
Here, we used the ObjectDoubleMaps factory class to create a mutable instance for MutableObjectDoubleMap.
在这里,我们使用ObjectDoubleMaps工厂类来为MutableObjectDoubleMap创建一个可变实例。
Now let’s add some entries:
现在我们来添加一些条目。
dObject.addToValue("price", 150.5);
dObject.addToValue("quality", 4.4);
dObject.addToValue("stability", 0.8);
2.2. A Primitive API Tree
2.2.一个原始的API树
In Eclipse Collections, there’s a base interface called PrimitiveIterable. This is the base interface for each of the primitive containers of the library. All are named PrimitiveTypeIterable, where PrimitiveType can be Int, Long, Short, Byte, Char, Float, Double, or Boolean.
在 Eclipse Collections 中,有一个名为 PrimitiveIterable 的基础接口。 这是该库中每个原始容器的基础接口。所有这些都被命名为PrimitiveTypeIterable,其中PrimitiveType可以是Int、Long、Short、Byte、Char、Float、Double或Boolean。
All these base interfaces, in turn, have their tree of XYMap implementations, which is divided on whether the map is mutable or immutable. As an example, for IntIntMap, we have MutableIntIntMap and ImmutableIntIntMap.
所有这些基础接口又有它们的XYMap实现树,这是按地图是可变的还是不可变的划分的。例如,对于IntMap,我们有MutableIntIntMap和ImmutableIntIntMap。
Finally, as we saw above, we have interfaces to cover all kinds of combinations of types for keys and values for both primitive and object values. So, for example, we can have IntObjectMap<K> for a primitive key with an Object value or ObjectIntMap<K> for its opposite case.
最后,正如我们在上面看到的,我们有接口来涵盖原始值和对象值的键和值的各种类型组合。因此,例如,我们可以用IntObjectMap<K>来表示带有Object值的原始键,或者用ObjectIntMap<K>来表示其相反情况。
3. HPPC
3.HPPC
HPPC is a library geared towards high performance and memory efficiency. This means that the library has less abstraction than others. However, this has the benefit of exposing the internals to useful low-level manipulation. It provides both maps and sets.
HPPC是一个面向高性能和内存效率的库。这意味着该库的抽象性比其他库要低。然而,这样做的好处是将内部结构暴露给有用的底层操作。它同时提供了映射和集合。
3.1. A Simple Example
3.1.一个简单的例子
Let’s start by creating a map that has an int key and a long value. Using this is pretty familiar:
让我们先创建一个有int键和long值的地图。使用这个是非常熟悉的。
IntLongHashMap intLongHashMap = new IntLongHashMap();
intLongHashMap.put(25, 1L);
intLongHashMap.put(150, Long.MAX_VALUE);
intLongHashMap.put(1, 0L);
intLongHashMap.get(150);
HPPC provides maps for all combinations of keys and values:
HPPC为所有的键和值的组合提供地图。
- Primitive key and primitive value
- Primitive key and object-type value
- Object-type key and primitive value
- Both Object-type key and value
Object-type maps support generics:
对象型映射支持泛型。
IntObjectOpenHashMap<BigDecimal>
ObjectIntOpenHashMap<LocalDate>
The first map has a primitive int key and a BigDecimal value. The second map has LocalDate for its keys and int for its values
第一个映射有一个原始的int键和一个BigDecimal值。第二个映射的键是LocalDate,其值是int。
3.2. Hash Maps vs Scatter Maps
3.2.哈希图与散点图
Due to the way key hashing and distribution functions are traditionally implemented, we could have collisions when hashing the keys. Depending on how keys are distributed, this can lead to performance problems on huge maps. By default, HPPC implements a solution that avoids this problem.
由于传统上实现密钥散列和分配功能的方式,我们在散列密钥时可能会发生碰撞。根据钥匙的分配方式,这可能会导致巨大地图上的性能问题。默认情况下,HPPC实现了一个避免这个问题的解决方案。
However, there is still a place for maps that have a simpler distribution function. This is useful if the maps are used as lookup tables or for counting, or if they don’t require lots of write operations once loaded. HHPC provides Scatter Maps to boost performance even more.
然而,对于那些具有更简单的分布功能的地图来说,仍有一席之地。这对如果地图被用作查找表或用于计数,或者如果它们在加载后不需要大量的写操作是很有用的。HHPC提供了散点图来进一步提高性能。
All the scatter-map classes maintain the same naming convention as maps, but instead use the word Scatter:
所有的散点图类都保持了与地图相同的命名规则,但却使用了Scatter这个词。
- IntScatterSet
- IntIntScatterMap
- IntObjectScatterMap<BigDecimal>
4. Fastutil
4.Fastutil
Fastutil is a fast and compact framework that provides type-specific collections including primitive type maps.
Fastutil是一个快速而紧凑的框架,它提供了特定类型的集合,包括原始类型映射。
4.1. Quick Example
4.1.快速实例
Similar to Eclipse Collections and HPPC. Fastutil also provides primitive-to-primitive and primitive-to-Object typed association maps.
类似于Eclipse Collections和HPPC。Fastutil还提供了基元到基元和基元到对象类型的关联图。
Let’s create an int to boolean map:
让我们创建一个int到boolean映射。
Int2BooleanMap int2BooleanMap = new Int2BooleanOpenHashMap();
And now, let’s add some entries:
而现在,让我们添加一些条目。
int2BooleanMap.put(1, true);
int2BooleanMap.put(7, false);
int2BooleanMap.put(4, true);
Then, we can retrieve values from it:
然后,我们可以从中检索出数值。
boolean value = int2BooleanMap.get(1);
4.2. In-Place Iteration
4.2.就地迭代
Standard JVM collections that implement the Iterable interface usually create a fresh temporary iterator object at each iteration step. With huge collections, this can create a garbage collection issue.
实现Iterable接口的标准JVM集合通常在每个迭代步骤创建一个新的临时迭代器对象。对于庞大的集合,这可能会产生一个垃圾回收问题。
Fastutil provides an alternative that greatly mitigates this:
Fastutil提供了一个替代方案,大大缓解了这种情况。
Int2FloatMap map = new Int2FloatMap();
//Add keys here
for(Int2FloatMap.Entry e : Fastutil.fastIterable(map)) {
//e will be reused on each iteration, so it will be only one object
}
Fastutil also provides the fastForeach method. This will take a Consumer functional interface and perform a lambda-expression for each loop:
Fastutil还提供了fastForeach方法。这将接受一个Consumer functional interface,并为每个循环执行一个lambda表达式。
Int2FloatMap map = new Int2FloatMap();
//Add keys here
Int2FloatMaps.fastForEach(map , e -> {
// e is also reused across iterations
});
This is very similar to the standard Java foreach construct:
这与标准的Java foreach结构非常相似。
Int2FloatMap map = new Int2FloatMap();
//Add keys here
map.forEach((key,value) -> {
// use each key/value entry
});
5. Conclusion
5.结论
In this article, we learned how to create primitive maps in Java using Eclipse Collections, HPPC, and Fastutil.
在这篇文章中,我们学习了如何使用Eclipse Collections、HPPC和Fastutil在Java中创建原始地图。
As always, the example code for this article is available over on GitHub.
像往常一样,本文的示例代码可在GitHub上获得。