2015-07-22 66 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,可能正弦不是那么大的问题,但在某些情况下,取决于特定的键提取函数,它可能很重要。 –