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で呼び出すことができるようにしたいのですpredicateが、抽出できた他の要件を実装する方法がよくわかりません。を拡張して抽象化することでできることは理解していFiniteSupplierますが、それは正しい方法ですか?

4

1 に答える 1

0

このメソッドは、および としてtest(int/Integer)使用できます。コンパイラは変換を行います:Predicate<Integer>IntPredicate

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

ただし、2 つの型は代入できないため、キャストできません。IntPredicate は Predicate を拡張しません。

したがって、FibSupplier を作成するときに ::test を使用するだけです。

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

または、コンストラクターでそれを行います。IntSupplier を受け取り、それを一般的な Supplier に変換する追加のコンストラクターを使用して、新しい抽象型 FiniteIntSupplier を導入します。

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