Java8 教程

Java8 并行数组操作

Arrays 类是 Java 中用于操作数组的工具类,提供了一系列实用的方法来处理数组。在 Java8 中,为 Arrays 类添加了许多并行化的操作,下面将详细说明。

Arrays.parallelSort 方法

Arrays.parallelSort 是 Java8 中引入的一个用于对数组进行并行排序的方法。它使用了并行排序-合并(sort-merge)算法,可利用多核 CPU 来提高排序的速度。

Arrays.parallelSort 方法存在以下特性:

  • 并行处理:通过将数组划分为子数组,并在多个线程中对这些子数组进行排序和合并,从而实现并行排序。为了执行并行任务,它使用了 Fork/Join 框架(ForkJoinPool)。

  • 自动选择算法:会根据数组的大小和运行环境自动决定是否使用并行排序。如果数组大小小于或等于某个临界值(通常为 8192,即 1 << 13),或者处理器只有一个核心,则会使用顺序的双轴快速排序(Dual-Pivot Quicksort)算法;否则,使用并行排序。

注意:使用并行排序在处理大规模数据时通常可以显著提高性能,但在数据量较小时,可能单线程的排序(如 Arrays.sort)会更快。

例如:使用 Arrays.parallelSort 静态方法对大数组进行排序。

// 初始化一个大 int 数组
int[] data = new int[10000];
for(int i = 0; i < data.length; i++) {
    data[i] = (int)(Math.random() * 10000);
}

// 对数组排序
Arrays.parallelSort(data);

// 输出排序后的结果
System.out.println(Arrays.toString(data));

上述示例,将采用递增的顺序对数组进行排序(默认),我们可以使用自定义的 Comparator 接口实现递减的顺序对数组排序,例如:

// 初始化一个大 int 数组
Integer[] data = new Integer[10000];
for(int i = 0; i < data.length; i++) {
    data[i] = (int)(Math.random() * 10000);
}

// 对数组排序
Arrays.parallelSort(data, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2 - o1;
    }
});

// 输出排序后的结果
System.out.println(Arrays.toString(data));

注意:如果你仔细观察,你会发现这些方法的名称中都带有 parallel(平行的;相似的,同时发生的;(计算机)并行的;并联的),毕竟用户并不关心排序是如何实现的。不过,API 的设计者们希望清晰地表示这些排序方法是并行执行的。这样就可以起到提示作用,避免比较器带来的副作用。

Arrays.parallelSetAll 方法

Arrays.parallelSetAll 方法用于并行地设置指定数组的所有元素,它使用提供的生成器函数来计算每个元素的值。该方法有多种签名形式,如下:

  • static void parallelSetAll(double[] array, IntToDoubleFunction generator)  并行设置指定数组的所有元素,使用提供的生成器函数计算每个元素。

  • static void parallelSetAll(int[] array, IntUnaryOperator generator)  并行设置指定数组的所有元素,使用提供的生成器函数计算每个元素。

  • static void parallelSetAll(long[] array, IntToLongFunction generator)  并行设置指定数组的所有元素,使用提供的生成器函数计算每个元素。

  • static <T> void parallelSetAll(T[] array, IntFunction<? extends T> generator)  并行设置指定数组的所有元素,使用提供的生成器函数计算每个元素。

示例:

修改 Arrays.parallelSort 方法的示例,使用 Arrays.parallelSetAll 方法重写初始化数组的部分,如下:

// 初始化一个大 int 数组
Integer[] data = new Integer[10000];
Arrays.parallelSetAll(data, new IntFunction<Integer>() {
    @Override
    public Integer apply(int value) {
        return (int)(Math.random() * 10000);
    }
});

// 对数组排序
Arrays.parallelSort(data, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2 - o1;
    }
});

// 输出排序后的结果
System.out.println(Arrays.toString(data));

Arrays.parallelPrefix 方法

Arrays.parallelPrefix 方法用于在给定的运算符基础上并行地更新数组。它会对数组的元素进行累积计算,并直接修改原始数组。这是什么意思?以下是一个示例。假设有数组 [1,2,3,4,...] 及乘法操作 x。当执行完 Arrays.parallelPrefix(values, (x, y) -> x * y ) 后,数组中包括:

[1, 1x2, 1×2×3, 1x2×3×4, ...]

parallelPrefix 方法有多种重载形式,如下:

  • static void parallelPrefix(double[] array, DoubleBinaryOperator op)  使用提供的函数并行累加给定数组中的每个元素。

  • static void parallelPrefix(double[] array, int fromIndex, int toIndex, DoubleBinaryOperator op)  为给定的数组子范围执行 parallelPrefix(double[], DoubleBinaryOperator)。

  • static void parallelPrefix(int[] array, IntBinaryOperator op)  使用提供的函数并行累加给定数组中的每个元素。

  • static void parallelPrefix(int[] array, int fromIndex, int toIndex, IntBinaryOperator op)  为给定的数组子范围执行 parallelPrefix(int[], IntBinaryOperator)。

  • static void parallelPrefix(long[] array, LongBinaryOperator op)  使用提供的函数并行累加给定数组中的每个元素。

  • static void parallelPrefix(long[] array, int fromIndex, int toIndex, LongBinaryOperator op)  为给定的数组子范围执行 parallelPrefix(long[], LongBinaryOperator)。

  • static <T> void parallelPrefix(T[] array, BinaryOperator<T> op)  使用提供的函数并行累加给定数组中的每个元素。

  • static <T> void parallelPrefix(T[] array, int fromIndex, int toIndex, BinaryOperator<T> op)  对给定数组的子范围执行 parallelPrefix(Object[],BinaryOperator)。

示例:

int[] data = {1,2,3,4,5};

// 并发更新数组
Arrays.parallelPrefix(data, new IntBinaryOperator() {
    @Override
    public int applyAsInt(int left, int right) {
        return left * right;
    }
});

System.out.println(Arrays.toString(data));
//结果:
//[1, 2, 6, 24, 120]
//其中:
// 1*2=2
// 1*2*3=6
// 1*2*3*4=24
// 1*2*3*4*5=120


说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号