java8 collection.spliterator()_用 Java 实现 Stream 高效混排与 Spliterator

原标题:用 Java 实现 Stream 高效混排与 Spliterator

编译: 唐尤华

链接: dzone.com/articles/a-case-study-of-implementing-an-efficient-shufflin>

对 Stream 执行排序操作只要调用排序 API 就好了,要实现相反的效果(混排)却并不简单。

本文介绍了如何使用 Java Stream `Collectors` 工厂方法与自定义 `Spliterator` 对 Stream 进行 Shuffle(混排),支持 Eager 与 Lazy 两种模式。

1. Eager Shuffle Collector

Heinz [在这篇文章][1]中给出了一种解决方案:将整个 Stream 转换为 list,对 list 执行 `Collections#shuffle`,再转为 Stream。像下面这样封装成一个复合操作:

[1]:https://www.javaspecialists.eu/archive/Issue258.html

```java

publicstatic Collector> toEagerShuffledStream() {

returnCollectors.collectingAndThen(

toList(),

list-> {

Collections.shuffle( list);

returnlist.stream();

});

}

```

这种方法适用于对 Steam 中所有元素进行混排。由于会提前对集合中所有元素进行 Shuffle,如果只处理其中一部分则效果不佳,极端情况比如 Stream 只包含1个元素。

让我们来看看一个简单基准测试的运行结果:

```java

@State(Scope.Benchmark)

publicclassRandomSpliteratorBenchmark {

privateList source;

@Param({ "1", "10", "100", "1000", "10000", "10000"})

publicintlimit;

@Param({ "100000"})

publicintsize;

@Setup(Level.Iteration)

publicvoidsetUp(){

source = IntStream.range( 0, size)

.boxed()

. map(Object::toString)

.collect(Collectors.toList());

}

@Benchmark

publicList eager() {

returnsource.stream()

.collect(toEagerShuffledStream())

.limit(limit)

.collect(Collectors.toList());

}

```

```shell

(limit) Mode Cnt Score Error Units

eager 1thrpt 5467.796± 9.074ops/s

eager 10thrpt 5467.694± 17.166ops/s

eager 100thrpt 5459.765± 8.048ops/s

eager 1000thrpt 5467.934± 43.095ops/s

eager 10000thrpt 5449.471± 5.549ops/s

eager 100000thrpt 5331.111± 5.626ops/s

```

从上面的数据可以看出,尽管运行结果 Stream 中元素不断增加,运行效果还是相当不错。因此,对整个集合提前混排太浪费了,尤其是元素较少的时候得分很差。

让我们看看来有什么好办法。

2. Lazy Shuffle Collector

为了节省 CPU 资源,与其对集合中所有元素预处理,不如根据需要只处理其中一部分。

为了达到这个效果,需要自定义一个 Spliterator 对所有对元素随机遍历,然后通过 `StreamSupport.stream` 构造创建一个 Stream 对象:

```java

publicclassRandomSpliterator implements Spliterator {

// ...

publicstatic Collector> toLazyShuffledStream() {

returnCollectors.collectingAndThen(

toList(),

list-> StreamSupport.stream(

newShuffledSpliterator<>( list), false));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值