Contents

FastUtils 简介

1. 简介

在本教程中,我们将研究*FastUtil *库。

首先,我们将编写其特定类型集合的一些示例。

然后,我们将分析赋予FastUtil名称的性能。

最后,让我们看一下FastUtil的 BigArray实用程序。

2.特点

FastUtil Java 库旨在扩展 Java 集合框架*。*它提供特定于类型的映射、集合、列表和队列,具有更小的内存占用和快速访问和插入。FastUtil还提供了一组实用程序,用于处理和操作大型(64 位)数组、集合和列表。

该库还包括大量用于二进制和文本文件的实用输入/输出类

其最新版本FastUtil 8还发布了一系列特定于类型的函数 ,扩展了 JDK 的函数式接口

2.1. 速度

**在许多情况下,FastUtil实现是最快的。**作者甚至提供了他们自己的深入基准报告 ,将其与类似的库(包括HPPC和 Trove)进行了比较。

在本教程中,我们将使用Java Microbench Harness (JMH) 定义我们自己的基准。

3. 全尺寸依赖

在通常的JUnit依赖项之上,我们将在本教程中使用FastUtilsJMH 依赖项。

我们的pom.xml文件中需要以下依赖项 :

<dependency>
    <groupId>it.unimi.dsi</groupId>
    <artifactId>fastutil</artifactId>
    <version>8.2.2</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.33</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.33</version>
    <scope>test</scope>
</dependency>

或者对于 Gradle 用户:

testCompile group: 'org.openjdk.jmh', name: 'jmh-core', version: '1.19'
testCompile group: 'org.openjdk.jmh', name: 'jmh-generator-annprocess', version: '1.19'
compile group: 'it.unimi.dsi', name: 'fastutil', version: '8.2.2'

3.1. 定制的 Jar 文件

由于缺少泛型,  FastUtils生成了大量类型特定的类。不幸的是,这会导致生成一个巨大的 jar 文件。

然而,对我们来说幸运的是,FastUtils包含一个find-deps.sh脚本,它允许生成更小、更集中的 jar,**其中仅包含我们想在应用程序中使用的类。

4. 特定类型的集合

在开始之前,让我们快速浏览一下实例化特定类型集合 的简单过程。让我们选择一个使用双精度存储键和值的HashMap

为此,  FastUtils提供了一个*Double2DoubleMap *接口和一个 *Double2DoubleOpenHashMap *实现:

Double2DoubleMap d2dMap = new Double2DoubleOpenHashMap();

现在我们已经实例化了我们的类,我们可以像使用 Java Collections API 中的任何Map 一样简单地填充数据:

d2dMap.put(2.0, 5.5);
d2dMap.put(3.0, 6.6);

最后,我们可以检查数据是否已正确添加:

assertEquals(5.5, d2dMap.get(2.0));

4.1. 表现

**FastUtils专注于其高性能实现。在本节中,我们将使用 JMH 来验证这一事实。**让我们将 Java Collections HashSet<Integer> 实现与 FastUtilIntOpenHashSet 进行比较。

首先,让我们看看如何实现 IntOpenHashSet

@Param({"100", "1000", "10000", "100000"})
public int setSize;
@Benchmark
public IntSet givenFastUtilsIntSetWithInitialSizeSet_whenPopulated_checkTimeTaken() {
    IntSet intSet = new IntOpenHashSet(setSize);
    for(int i = 0; i < setSize; i++) {
        intSet.add(i);
    }
    return intSet; 
}

上面,我们只是声明了IntSet接口的 IntOpenHashSet实现。我们还 使用 @Param 注解声明了初始大小setSize

简而言之,这些数字被输入 JMH 以生成一系列具有不同集合大小的基准测试。

接下来,让我们使用 Java Collections 实现做同样的事情:

@Benchmark
public Set<Integer> givenCollectionsHashSetWithInitialSizeSet_whenPopulated_checkTimeTaken() {
    Set<Integer> intSet = new HashSet<>(setSize);
    for(int i = 0; i < setSize; i++) {
        intSet.add(i);
    }
    return intSet;
}

最后,让我们运行基准测试并比较两个实现:

Benchmark                                     (setSize)  Mode  Cnt     Score   Units
givenCollectionsHashSetWithInitialSizeSet...        100  avgt    2     1.460   us/op
givenCollectionsHashSetWithInitialSizeSet...       1000  avgt    2    12.740   us/op
givenCollectionsHashSetWithInitialSizeSet...      10000  avgt    2   109.803   us/op
givenCollectionsHashSetWithInitialSizeSet...     100000  avgt    2  1870.696   us/op
givenFastUtilsIntSetWithInitialSizeSet...           100  avgt    2     0.369   us/op
givenFastUtilsIntSetWithInitialSizeSet...          1000  avgt    2     2.351   us/op
givenFastUtilsIntSetWithInitialSizeSet...         10000  avgt    2    37.789   us/op
givenFastUtilsIntSetWithInitialSizeSet...        100000  avgt    2   896.467   us/op

这些结果清楚地表明FastUtils实现比 Java Collections 替代方案性能更高。

5. 大集合

FastUtils的另一个重要特性是能够使用 64 位数组。**默认情况下,Java 中的数组限制为 32 位。

首先,让我们看一下Integer类型的BigArrays类。**IntBigArrays 提供了用于处理二维整数数组的静态方法。**通过使用这些提供的方法,我们基本上可以将我们的数组包装成一个更加用户友好的一维数组。

让我们来看看这是如何工作的。

首先,我们首先初始化一个一维数组,然后使用IntBigArraywrap方法将其转换为二维数组:

int[] oneDArray = new int[] { 2, 1, 5, 2, 1, 7 };
int[][] twoDArray = IntBigArrays.wrap(oneDArray.clone());

我们应该确保使用clone方法来确保数组的深拷贝。

现在,就像我们处理List或 Map一样,我们可以使用get方法访问元素 :

int firstIndex = IntBigArrays.get(twoDArray, 0);
int lastIndex = IntBigArrays.get(twoDArray, IntBigArrays.length(twoDArray)-1);

最后,让我们添加一些检查以确保我们的IntBigArray返回正确的值:

assertEquals(2, firstIndex);
assertEquals(7, lastIndex);