技术编程5万字:Stream和Lambda表达式最佳实践2( 六 )


上面我们讨论了Spliterator一些关键方法 , 现在我们举一个具体的例子:@AllArgsConstructor@Datapublic class CustBook {private String name;}复制代码
先定义一个CustBook类 , 里面放一个name变量 。
定义一个方法 , 来生成一个CustBook的list:public static List
generateElements() {return Stream.generate(() -> new CustBook("cust book")).limit(1000).collect(Collectors.toList());}复制代码
我们定义一个call方法 , 在call方法中调用了tryAdvance方法 , 传入了我们自定义的处理方法 。 这里我们修改book的name,并附加额外的信息 。 public String call(Spliterator
spliterator) {int current = 0;while (spliterator.tryAdvance(a -> a.setName("test name".concat("- add new name")))) {current++;}return Thread.currentThread().getName() + ":" + current;}复制代码
最后 , 写一下测试方法:@Testpublic void useTrySplit(){Spliterator
split1 = SpliteratorUsage.generateElements().spliterator();Spliterator
split2 = split1.trySplit();log.info("before tryAdvance: {}",split1.estimateSize());log.info("Characteristics {}",split1.characteristics());log.info(call(split1));log.info(call(split2));log.info("after tryAdvance {}",split1.estimateSize());}复制代码
运行的结果如下:23:10:08.852 [main] INFO com.flydean.SpliteratorUsage - before tryAdvance: 50023:10:08.857 [main] INFO com.flydean.SpliteratorUsage - Characteristics 1646423:10:08.858 [main] INFO com.flydean.SpliteratorUsage - main:50023:10:08.858 [main] INFO com.flydean.SpliteratorUsage - main:50023:10:08.858 [main] INFO com.flydean.SpliteratorUsage - after tryAdvance 0复制代码
List总共有1000条数据 , 调用一次trySplit之后 , 将List分成了两部分 , 每部分500条数据 。
注意 , 在tryAdvance调用之后 , estimateSize变为0 , 表示所有的元素都已经被处理完毕 。
再看一下这个Characteristics=16464 , 转换为16进制:Ox4050 = ORDERED or SIZED or SUBSIZED 这三个的或运算 。
这也是ArrayList的基本特征 。 13. break stream的foreach
我们通常需要在java stream中遍历处理里面的数据 , 其中foreach是最最常用的方法 。
但是有时候我们并不想处理完所有的数据 , 或者有时候Stream可能非常的长 , 或者根本就是无限的 。
一种方法是先filter出我们需要处理的数据 , 然后再foreach遍历 。
那么我们如何直接break这个stream呢?今天本文重点讲解一下这个问题 。 13.1 使用Spliterator
上篇文章我们在讲Spliterator的时候提到了 , 在tryAdvance方法中 , 如果返回false , 则Spliterator将会停止处理后续的元素 。
通过这个思路 , 我们可以创建自定义Spliterator 。
假如我们有这样一个stream:Stream
ints = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);复制代码
我们想定义一个操作 , 当x > 5的时候就停止 。
我们定义一个通用的Spliterator:public class CustomSpliterator extends Spliterators.AbstractSpliterator{private Spliterator splitr;private Predicate predicate;private volatile boolean isMatched = true;public CustomSpliterator(Spliterator splitr, Predicate predicate) {super(splitr.estimateSize(), 0);this.splitr = splitr;this.predicate = predicate;}@Overridepublic synchronized boolean tryAdvance(Consumer
consumer) {boolean hadNext = splitr.tryAdvance(elem -> {if (predicate.test(elem) && isMatched) {consumer.accept(elem);} else {isMatched = false;}});return hadNext && isMatched;}}复制代码


推荐阅读