0

考虑到我有以下课程:

public class Problem2 extends Problem<Integer> {
    @Override
    public void run() {
        result = toList(new FibSupplier(i -> (i <= 4_000_000)))
                .stream()
                .filter(i -> (i % 2 == 0))
                .mapToInt(i -> i)
                .sum();
    }

    @Override
    public String getName() {
        return "Problem 2";
    }

    private static <E> List<E> toList(final Iterator<E> iterator) {
        List<E> list = new ArrayList<>();
        while (iterator.hasNext()) {
            list.add(iterator.next());
        }
        return list;
    }

    private class FibSupplier implements Iterator<Integer> {
        private final IntPredicate hasNextPredicate;

        private int beforePrevious = 0;
        private int previous = 1;

        public FibSupplier(final IntPredicate hasNextPredicate) {
            this.hasNextPredicate = hasNextPredicate;
        }

        @Override
        public boolean hasNext() {
            return hasNextPredicate.test(previous);
        }

        @Override
        public Integer next() {
            int result = beforePrevious + previous;
            beforePrevious = previous;
            previous = result;
            return result;
        }
    } 
}

如果你看一下FibSupplier你会发现它暴露了一个普遍的问题,即使它在这里有一个专门的实现,我设法提取的是:

  • 它有一个Predicate.
  • 它具有初始变量。
  • 它有一个需要由谓词测试的变量。
  • 它有一个自定义next()方法。

我尝试通过以下方式来概括这一点,请注意,我现在使用通用版本而不是专用整数版本:

public class FiniteSupplier<E> implements Iterator<E> {
    private final Predicate<E> predicate;

    public FiniteSupplier(final Predicate<E> predicate) {
        this.predicate = predicate;
    }

    @Override
    public boolean hasNext() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public E next() {
        throw new UnsupportedOperationException("Not supported yet.");
    }  
}

我希望能够FiniteSupplier用 a调用predicate,但是现在我真的不知道如何实现我设法提取的其他要求。我知道可以通过扩展FiniteSupplier和使其抽象来完成,但这是正确的方法吗?

4

1 回答 1

0

该方法test(int/Integer)可用于 asPredicate<Integer>和 as IntPredicate。编译器进行转换:

IntPredicate ip = (i) -> i>0;
Predicate<Integer> pi = (i) -> i>0;
Predicate<Integer> ip2pi = ip::test;
IntPredicate pi2ip = pi::test;

但是您不能强制转换这两种类型,因为它们不可分配。IntPredicate 不扩展 Predicate。

因此,在创建 FibSupplier 时只需使用 ::test:

new FibSupplier(p) => new FibSupplier(p::test) 

或者在构造函数中这样做。我将引入一个新的抽象类型 FiniteIntSupplier 和一个额外的构造函数,该构造函数接受一个 IntSupplier 并将其转换为一般供应商:

public FiniteIntSupplier(IntPredicate p) {
  this(p::test);
}
于 2014-05-27T13:59:07.027 回答