Java 8 的并行流是改进大型集合处理的直接方法。本文在此基础上介绍了三种不同的改进算法,并通过比较,给出了能够带来更优越性能的方法。
和许多其他编程语言类似,Java拥有一组数据结构对象,可以被用来表示某些单个单元,及其可以执行的一组操作。从处理大数据量的计算程序来看,其典型操作会涉及到对每个对象进行转换等各种集合。在本文中,我们将借用ETL(提取、转换和加载)的基本概念,将提取/捕获到的数据从原来的形式,转换为指定的形式,以便将其存放到另一个数据库中。当然,我们会在此讲述数据库元素的转换、抽象操作的概念,以便你更好地理解集合处理的本质。
1.基础知识
从Java 1.2开始,我们便主要依赖于作为集合层级结构的java.util.Collection根接口。而在Java 7发布之前,能够显著提升大型集合的处理性能的唯一方法是:并行化操作。不过,随着Java 8的出现,新的java.util.stream包提供了支持元素流进行功能性样式(functional-style)操作的Stream API。Stream API通过被集成到Collections API中,可以对集合进行诸如顺序或并行的map-reduce转换等批量操作。
从那时起,Java便提供了一种原生的方式,来尝试着改进应用于集合的转换操作的并行化性能。之所以被称为是一种“尝试”的策略,其原因在于它只是简单地使用了并行流式操作,并不能保证一定会有更好的性能。毕竟其他潜在的因素也可能产生影响。尽管如此,并行流提供了寻求改进处理性能的一个思路和起点。
下面,我将对一个大型的Java集合采用简单的转换操作,比较原生的顺序和并行处理、以及三种基于其他算法的并行流策略,在性能上的优劣。
2.转换操作
针对转换操作,我们定义了一个功能性的接口。如下面的代码段所示,你只需要将一个 R 类型的元素,应用到变换操作上,便可返回一个 S 类型的变换对象。
Java
@FunctionalInterface public interface ElementConverter<R, S> { S apply(R param); }
该操作旨在将一个作为参数提供的字符串,转换为大写字母的形式。下面的两个代码段分别创建了两个ElementConverter接口的实现。其中的一个是将某个字符串转换为大写字符串:
Java
public class UpperCaseConverter implements ElementConverter<String, String> { @Override public String apply(String param) { return param.toUpperCase(); } }
另一个是对集合执行相同的操作:
Java
public class CollectionUpperCaseConverter implements ElementConverter<List<String>, List<String>> { @Override public List<String> apply(List<