有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

根据以前的计算结果停止java流计算

如何打破基于先前结果的流计算?如果那条小溪很明显的话。过滤器(…)。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.5sampleData.size() = 10_000_000,并且第一个5_000_000元素使predicate::test失败,则没有理由验证最后的5_000_000元素(count()永远不会大于5_000_000


共 (3) 个答案

  1. # 1 楼答案

    老实说,我不太确定这是否正确,我希望有人会来检查一下,但下面是我使用自定义拆分器的想法:

     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();
    

    同样,这仅适用于已知大小的拆分器

  2. # 2 楼答案

    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::test一样创建一个对现有Predicate测试方法的方法引用。只需将Predicate传递给filter方法。上面的代码也使用了predicate.negate()而不是predicate.negate()::test

  3. # 3 楼答案

    Set<String> sampleData = downloadFromWeb();  
    int size = (int) (sampleData.size() * coefficient);
    return sampleData.stream().filter(predicate::test).limit(size + 1).count() > size;