2015-07-22 198 views
1
final int[] brr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }; 

for (int i : brr) { 
    System.out.println(Math.sin(i)); 
} 

final int leastIdx = Arrays.stream(brr).min(Comparator.comparingDouble(i -> Math.sin(i))).get(); 

leastIdx應該返回爲4,但我不能得到它編譯。 感謝任何見解。Java 8:比較器比較雙類型不匹配

The method min() in the type IntStream is not applicable for the 
arguments (Comparator.comparingDouble((<no type> i) -> Math.sin(i))) 

回答

4

IntStream#min不帶比較器;它只是在流中找到最小的int。你必須要麼轉換爲Stream<Integer>

Arrays.stream(brr).boxed() 
     .min(comparingDouble(i -> Math.sin(i))) 
     .get(); 

或使用reduce計算分:

Arrays.stream(brr) 
     .reduce((x,y) -> Math.sin(x) > Math.sin(y) ? y : x) 
     .getAsInt(); 

leastIdx應該返回4

你流實際上是試圖找到int與最小的Math.sin,而不是那個int的索引。如果你想找到索引,則需要流過的指標,而不是在值:

int leastIdx = IntStream.range(0, brr.length).boxed() 
     .min(comparingDouble(i->Math.sin(brr[i]))) 
     .get(); 

,或者,如果你願意犧牲清晰度來避免裝箱:

int leastIdx = IntStream.range(0, brr.length) 
     .reduce((x,y) -> Math.sin(brr[x]) > Math.sin(brr[y]) ? y : x) 
     .getAsInt(); 
2

的提出的解決方案有一個缺陷:他們幾乎爲每個元素計算正弦兩次。因此,對於1000個輸入元素,您將必須計算正弦約2000次。

有兩個解決方案涉及我StreamEx庫,每個流元素計算正弦恰好一次:

final int leastIdx = IntStreamEx 
     .ofIndices(brr).boxed() 
     .minByDouble(i -> Math.sin(brr[i])).get(); 

或者:

final int leastIdx = (int) IntStreamEx.of(brr) 
     .mapToObj(Math::sin) 
     .collect(MoreCollectors.minIndex()).getAsLong(); 

無論您輸入返回4。不幸的是,目前他們都涉及拳擊。目前StreamEx沒有提供消除裝箱和兩次正弦計算的方法。

+1

我不會在乎,除非一個探查者告訴我兩次計算'罪'是一個問題。它不是不太可能被優化掉。 – Holger

+0

@Holger,可能正弦不是那麼大的問題,但在某些情況下,取決於特定的鍵提取函數,它可能很重要。 –