如何根据以前的结果打破流计算?如果很明显stream.filter(...)。count()会小于某个数字 - 如何停止流计算?
我有以下代码检查某些sampleData
是否通过predicate
测试:
// sampleData.size() may be greater than 10.000.000
Set<String> sampleData = downloadFromWeb();
return sampleData.stream().filter(predicate::test).count() > sampleData.size() * coefficient;
我可以有数千sampleData
。问题是这段代码无效。例如,如果coefficient
等于0.5
,sampleData.size() = 10_000_000
和第一个5_000_000
元素未通过predicate::test
- 则没有理由验证上一个5_000_000
元素( count()永远不会大于5_000_000
)。
答案 0 :(得分:4)
说实话,我不太确定这是否正确,我希望有人会来回顾一下,但这是我使用自定义分裂器的想法:
static class CustomSpl<T> extends AbstractSpliterator<T> {
private Spliterator<T> source;
private int howMany;
private int coefficient;
private Predicate<T> predicate;
private T current;
private long initialSize;
private void setT(T t) {
this.current = t;
}
public CustomSpl(Spliterator<T> source, int howMany, int coefficient, Predicate<T> predicate, long initialSize) {
super(source.estimateSize(), source.characteristics());
this.source = source;
this.howMany = howMany;
this.coefficient = coefficient;
this.predicate = predicate;
this.initialSize = initialSize;
}
@Override
public boolean tryAdvance(Consumer<? super T> action) {
boolean hasMore = source.tryAdvance(this::setT);
System.out.println(current);
if (!hasMore) {
return false;
}
if (predicate.test(current)) {
++howMany;
}
if (initialSize - howMany <= coefficient) {
return false;
}
action.accept(current);
return true;
}
}
例如,这只会产生4个元素,因为我们只关心有一个系数5
:
Spliterator<Integer> sp = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).stream().spliterator();
long count = StreamSupport.stream(new CustomSpl<>(sp, 0, 5, x -> x > 3, sp.getExactSizeIfKnown()), false)
.count();
这也适用于只有已知尺寸的分裂器。
答案 1 :(得分:4)
ZhekaKozlov’s answer正朝着正确的方向前进,但缺乏否定。对于大于特定阈值的匹配,非匹配元素的数量必须小于“大小 - 阈值”。如果我们测试不匹配的元素是否更小,我们可以应用limit
一旦它们变大就停止:
Set<String> sampleData = downloadFromWeb();
final long threshold = sampleData.size()-(long)(sampleData.size() * coefficient);
return sampleData.stream()
.filter(predicate.negate()).limit(threshold+1).count() < threshold;
顺便说一句,没有理由创建对Predicate
的现有predicate::test
的测试方法的方法引用,例如Predicate
。只需将filter
传递给predicate.negate()
方法即可。上面的代码也使用predicate.negate()::test
代替pug
...
答案 2 :(得分:0)
Max Chars