返回介绍

6.4 并行流与并行排序

发布于 2024-08-21 22:20:21 字数 1968 浏览 0 评论 0 收藏 0

Java 8中,可以在接口不变的情况下,将流改为并行流。这样,就可以很自然地使用多线程进行集合中的数据处理。

6.4.1 使用并行流过滤数据

现在让我们考虑这么一个简单的案例,我们希望可以统计1~1000000内所有的质数的数量。首先,我们需要一个判断质数的函数:

public class PrimeUtil {
  public static boolean isPrime(int number) {
    int tmp = number;
    if (tmp < 2) {
      return false;
    }
    for (int i = 2; Math.sqrt(tmp) >= i; i++) {
      if (tmp % i == 0) {
        return false;
      }
    }
    return true;
  }
}

上述函数给定一个数字,如果这个数字是质数就返回true,否则返回false。

接着,使用函数式编程统计给定范围内所有的质数:

IntStream.range(1, 1000000).filter(PrimeUtil::isPrime).count();

上述代码首先生成一个1到1000000的数字流。接着使用过滤函数,只选择所有的质数,最后进行数量统计。

上述代码是串行的,将它改造成并行计算非常简单,只需要将流并行化即可:

IntStream.range(1, 1000000).parallel().filter(PrimeUtil::isPrime).count();

上述代码中,首先parallel()方法得到一个并行流,接着,在并行流上进行过滤,此时,PrimeUtil.isPrime()函数会被多线程并发调用,应用于流中的所有元素。

6.4.2 从集合得到并行流

在函数式编程中,我们可以从集合得到一个流或者并行流。下面这段代码试图统计集合内所有学生的平均分:

List<Student> ss=new ArrayList<Student>();
double ave=ss.stream().mapToInt(s->s.score).average().getAsDouble();

从集合对象List中,我们使用stream()方法可以得到一个流。如果希望将这段代码并行化,则可以使用parallelStream()函数。

double ave=ss.parallelStream().mapToInt(s->s.score).average().getAsDouble();

可以看到,将原有的串行方式改造成并行执行是非常容易的。

6.4.3 并行排序

除了并行流外,对于普通数组,Java 8中也提供了简单的并行功能。比如,对于数组排序,我们有Arrays.sort()方法。当然这是串行排序,但在Java 8中,我们可以使用新增的Arrays. parallelSort()方法直接使用并行排序。

比如,你可以这样使用:

int[] arr=new int[10000000]; Arrays.parallelSort(arr);

除了并行排序外,Arrays中还增加了一些API用于数组中数据的赋值,比如:

public static void setAll(int[] array, IntUnaryOperator generator)

这是一个函数式味道很浓的接口,它的第2个参数是一个函数式接口。如果我们想给数组中每一个元素都附上一个随机值,则可以这么做:

Random r=new Random();
Arrays.setAll(arr, (i)->r.nextInt());

当然,以上过程是串行的。但是只要使用setAll()对应的并行版本,你就可以很快将它执行在多个CPU上:

Random r=new Random();
Arrays.parallelSetAll (arr, (i)->r.nextInt());

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文