Spliterator Java 8 - 自定义实现
Spliterator Java 8 - custom implementation
我正在学习这个 Java 8 功能,我真的很难理解 Spliterator
接口的 trySplit()
方法实现,以防自定义 类 并行处理生成的 Stream
.
任何人都可以帮我提供一些带有清晰示例的好教程吗?
An ideal trySplit method efficiently (without traversal) divides its
elements exactly in half, allowing balanced parallel computation. Many
departures from this ideal remain highly effective; for example, only
approximately splitting an approximately balanced tree, or for a tree
in which leaf nodes may contain either one or two elements, failing to
further split these nodes. However, large deviations in balance and/or
overly inefficient trySplit mechanics typically result in poor
parallel performance.
以及带注释的方法结构
public Spliterator<T> trySplit() {
int lo = origin; // divide range in half
int mid = ((lo + fence) >>> 1) & ~1; // force midpoint to be even
if (lo < mid) { // split out left half
origin = mid; // reset this Spliterator's origin
return new TaggedArraySpliterator<>(array, lo, mid);
}
else // too small to split
return null;
}
如需更多曝光,请阅读 https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html
这里是实现 Spliterator 的例子。
public class Payment {
private String category;
private double amount;
public Payment(double amount, String category) {
this.amount = amount;
this.category = category;
}
public String getCategory() {
return category;
}
public double getAmount() {
return amount;
}
}
TrySplit 实现:
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;
public class PaymentBatchSpliterator implements Spliterator<Payment> {
private List<Payment> paymentList;
private int current;
private int last; // inclusive
public PaymentBatchSpliterator(List<Payment> payments) {
this.paymentList = payments;
last = paymentList.size() - 1;
}
public PaymentBatchSpliterator(List<Payment> payments, int start, int last) {
this.paymentList = payments;
this.current = start;
this.last = last;
}
@Override
public boolean tryAdvance(Consumer<? super Payment> action) {
if (current <= last) {
action.accept(paymentList.get(current));
current++;
return true;
}
return false;
}
@Override
public Spliterator<Payment> trySplit() {
if ((last - current) < 100) {
return null;
}
// first stab at finding a split position
int splitPosition = current + (last - current) / 2;
// if the categories are the same, we can't split here, as we are in the middle of a batch
String categoryBeforeSplit = paymentList.get(splitPosition-1).getCategory();
String categoryAfterSplit = paymentList.get(splitPosition).getCategory();
// keep moving forward until we reach a split between categories
while (categoryBeforeSplit.equals(categoryAfterSplit)) {
splitPosition++;
categoryBeforeSplit = categoryAfterSplit;
categoryAfterSplit = paymentList.get(splitPosition).getCategory();
}
// safe to create a new spliterator
PaymentBatchSpliterator secondHalf = new PaymentBatchSpliterator(paymentList,splitPosition,last);
// reset our own last value
last = splitPosition - 1;
return secondHalf;
}
@Override
public long estimateSize() {
return last - current;
}
@Override
public int characteristics() {
return 0;
}
}
是来自 GitHub Reference
的示例
我正在学习这个 Java 8 功能,我真的很难理解 Spliterator
接口的 trySplit()
方法实现,以防自定义 类 并行处理生成的 Stream
.
任何人都可以帮我提供一些带有清晰示例的好教程吗?
An ideal trySplit method efficiently (without traversal) divides its elements exactly in half, allowing balanced parallel computation. Many departures from this ideal remain highly effective; for example, only approximately splitting an approximately balanced tree, or for a tree in which leaf nodes may contain either one or two elements, failing to further split these nodes. However, large deviations in balance and/or overly inefficient trySplit mechanics typically result in poor parallel performance.
以及带注释的方法结构
public Spliterator<T> trySplit() {
int lo = origin; // divide range in half
int mid = ((lo + fence) >>> 1) & ~1; // force midpoint to be even
if (lo < mid) { // split out left half
origin = mid; // reset this Spliterator's origin
return new TaggedArraySpliterator<>(array, lo, mid);
}
else // too small to split
return null;
}
如需更多曝光,请阅读 https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html
这里是实现 Spliterator 的例子。
public class Payment {
private String category;
private double amount;
public Payment(double amount, String category) {
this.amount = amount;
this.category = category;
}
public String getCategory() {
return category;
}
public double getAmount() {
return amount;
}
}
TrySplit 实现:
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;
public class PaymentBatchSpliterator implements Spliterator<Payment> {
private List<Payment> paymentList;
private int current;
private int last; // inclusive
public PaymentBatchSpliterator(List<Payment> payments) {
this.paymentList = payments;
last = paymentList.size() - 1;
}
public PaymentBatchSpliterator(List<Payment> payments, int start, int last) {
this.paymentList = payments;
this.current = start;
this.last = last;
}
@Override
public boolean tryAdvance(Consumer<? super Payment> action) {
if (current <= last) {
action.accept(paymentList.get(current));
current++;
return true;
}
return false;
}
@Override
public Spliterator<Payment> trySplit() {
if ((last - current) < 100) {
return null;
}
// first stab at finding a split position
int splitPosition = current + (last - current) / 2;
// if the categories are the same, we can't split here, as we are in the middle of a batch
String categoryBeforeSplit = paymentList.get(splitPosition-1).getCategory();
String categoryAfterSplit = paymentList.get(splitPosition).getCategory();
// keep moving forward until we reach a split between categories
while (categoryBeforeSplit.equals(categoryAfterSplit)) {
splitPosition++;
categoryBeforeSplit = categoryAfterSplit;
categoryAfterSplit = paymentList.get(splitPosition).getCategory();
}
// safe to create a new spliterator
PaymentBatchSpliterator secondHalf = new PaymentBatchSpliterator(paymentList,splitPosition,last);
// reset our own last value
last = splitPosition - 1;
return secondHalf;
}
@Override
public long estimateSize() {
return last - current;
}
@Override
public int characteristics() {
return 0;
}
}
是来自 GitHub Reference
的示例