2014-02-22 10 views
0

考慮到我有下面的類:如何將FibSupplier轉變爲一般的有限供應商?

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."); 
    } 
} 

我希望能夠調用FiniteSupplierpredicate但是現在我不知道如何實現我設法提取的其他需求。我知道這可以通過擴展FiniteSupplier並使其變爲抽象來完成,但這是做到這一點的正確方法嗎?

+1

我不理解的廣義和專業在這方面的意思。恐怕我無法真正瞭解這個問題。 –

+0

爲什麼你需要一個謂詞呢?我期望一個'FibSupplier'只是*永久*從'hasNext'返回'true' ... –

+0

@JonSkeet我希望能夠在一定條件下停止供應,除了提供的整數的絕對數量之外,因此爲什麼我想要謂詞。如果還有其他方法可以解決這個問題,那麼請建議。 – skiwi

回答

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; 

但是您不能轉換這兩種類型,因爲它們不可分配。 IntPredicate不擴展謂詞。

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

或做在一個構造函數:

當您創建FibSupplier所以只使用::測試。我介紹一個新的抽象類型FiniteIntSupplier一個額外的構造函數的IntSupplier並將其轉換成一般的供應商:

public FiniteIntSupplier(IntPredicate p) { 
    this(p::test); 
}