在Java8的当前流方法中使用流方法
我得到了一组整数,我想计算流包含的在Java8的当前流方法中使用流方法,java,java-8,java-stream,Java,Java 8,Java Stream,我得到了一组整数,我想计算流包含的max()整数的数量。max()方法来自流API 我本来打算做这样的事 int count = Arrays.stream(myIntArray) .filter(i -> i == max()) .count(); System.out.printf("Count: %d", count); 我不能从我的forEach()方法中调用max()方法,因为这不是Streams的工作方式–那么我该怎么做才能让它
max()
整数的数量。max()
方法来自流API
我本来打算做这样的事
int count = Arrays.stream(myIntArray)
.filter(i -> i == max())
.count();
System.out.printf("Count: %d", count);
我不能从我的
forEach()
方法中调用max()
方法,因为这不是Streams的工作方式–那么我该怎么做才能让它工作呢?你不能做这样的事情,这会带来很多麻烦。编写所需内容的最简单方法是两个阶段:
int max = Arrays.stream(array).max().getAsInt();
int count = (int) Arrays.stream(array).filter(i -> i == max).count();
如果你坚持一次完成,我会写下
int[] maxAndCount = Arrays.stream(array).collect(
() -> new int[2], // first max, then count
(maxAndCount, i) -> {
if (i > maxAndCount[0] || maxAndCount[1] == 0) {
maxAndCount[0] = i;
maxAndCount[1] = 1;
} else if (i == maxAndCount[0]) {
maxAndCount[1]++;
}
},
(maxAndCount1, maxAndCount2) -> {
if (maxAndCount1[0] < maxAndCount2[0]) {
maxAndCount1[0] = maxAndCount2[0];
maxAndCount1[1] = maxAndCount2[1];
} else if (maxAndCount1[0] == maxAndCount2[0]) {
maxAndCount1[1] += maxAndCount2[1];
}
});
int count = maxAndCount[1];
int[]maxAndCount=Arrays.stream(array.collect)(
()->新的int[2],//首先是max,然后是count
(maxAndCount,i)->{
如果(i>maxAndCount[0]| | maxAndCount[1]==0){
maxAndCount[0]=i;
maxAndCount[1]=1;
}else如果(i==maxAndCount[0]){
maxAndCount[1]++;
}
},
(maxAndCount1,maxAndCount2)->{
if(maxAndCount1[0]
…但老实说,简单的两阶段版本很难击败。(坦率地说,我希望它的性能会更好。)如果您想使用streams来完成此任务,您必须使用一个保存状态的对象-您可以使用一个自定义收集器来完成此任务:
public static void main(String[] args) {
final int[] arr = {1, 2, 3, 4, 5, 1, 2, 3, 5};
class MaxCollector {
int max = Integer.MIN_VALUE;
int count = 0;
public void accept(int value) {
if (max < value) {
max = value;
count = 1;
} else if (max == value) {
count++;
}
}
public void combine(MaxCollector other) {
if (max == other.max) {
count += other.count;
} else if (max < other.max) {
max = other.max;
count = other.count;
}
}
}
final MaxCollector m = Arrays.stream(arr).collect(
MaxCollector::new, MaxCollector::accept, MaxCollector::combine);
System.out.println(m.max + " : " + m.count);
}
publicstaticvoidmain(字符串[]args){
final int[]arr={1,2,3,4,5,1,2,3,5};
类MaxCollector{
int max=整数的最小值;
整数计数=0;
公共无效接受(int值){
如果(最大值<值){
最大值=最大值;
计数=1;
}else if(max==值){
计数++;
}
}
公共无效联合收割机(MaxCollector其他){
if(max==other.max){
计数+=其他.计数;
}else if(最大值<其他最大值){
max=other.max;
count=other.count;
}
}
}
最终MaxCollector m=Arrays.stream(arr.collect)(
MaxCollector::new、MaxCollector::accept、MaxCollector::combine);
系统输出打印项次(m.max+“:”+m.count);
}
您也可以使用下面的streams代码(带内联注释),该代码给出了出现的次数(最大次数):
您可以先获取最大值,然后再进行流式处理
int max = Arrays.stream(myIntArray).max().getAsInt();
int count = Arrays.stream(myIntArray)
.filter(i -> i == max)
.count();
System.out.printf("Count: %d", count);
只需在Collections类中使用frequency方法。它的存在正是为了这个目的。什么是
max()
返回?@m_callensmax()
返回数组流中的最大整数。您想调用属于该流的max方法还是您自己的自定义max方法?对不起,我正在尝试在流API中使用max()方法。这还不够清楚。@Aphex您知道您不能在lambda中使用“count”,因为它必须是“final”才能被允许,并且在声明为“final”时您不能更改“count”的值。@JacobG。读取UsinggetAsInt()
的返回类型意味着空数组将因NoSuchElementException
而失败,而不是导致最大计数0
(没有最大元素,因此它们的计数为0)。由于OP只对计数感兴趣,而不是对最大值本身感兴趣,因此使用orElse(0)
会更好。好奇的是:为什么您希望迭代数组两次比在一次迭代中收集max
和count
更快?如果您的答案是“因为int[2]
数组的索引访问”,那么我会说使用类可以解决这个问题。请看另一个问题。不确定“没有要处理的堆变量”是什么意思,因为您的代码在调用筛选器lambda表达式时使用了堆。调用filter()
谓词或collect()
累加器大致相同,但双流意味着您有向下游发送两次迭代值的开销,这是在使用堆。--无论如何,这是一个没有实际意义的观点,因为如果你真的想要快速,你就不会使用stream,只是一个常规的for
循环,所以我同意双行程序更好/更简单/更容易理解,但性能不是原因。投票结果是肯定的,但我仍然认为你应该使用orElse(0)
。
int max = Arrays.stream(myIntArray).max().getAsInt();
int count = Arrays.stream(myIntArray)
.filter(i -> i == max)
.count();
System.out.printf("Count: %d", count);