Java 如何找到流的标准化平均值?

Java 如何找到流的标准化平均值?,java,Java,我被困在如何找到流的标准化平均值上。流包含数字,我正在尝试找到标准化的平均值。该方程是标准化的mean=(平均流-最小流)/(最大流-最小流) normalizedStream(Stream.of(1,2,3,4,5))将给我0.5 public static double normalizedMean(Stream<Integer> stream) { Integer max = max(stream); Integer min = min(stream);

我被困在如何找到流的标准化平均值上。流包含数字,我正在尝试找到标准化的平均值。该方程是标准化的
mean=(平均流-最小流)/(最大流-最小流)

normalizedStream(Stream.of(1,2,3,4,5))
将给我0.5

public static double normalizedMean(Stream<Integer> stream) {
    Integer max = max(stream);
    Integer min = min(stream);
    Integer sum = sum(stream);
    long count = count(stream);
    return (double) ((sum / count) - min) / (max - min);
}
publicstaticdoublenormalizedmean(流){
整数max=max(流);
整数min=min(流);
整数和=和(流);
长计数=计数(流);
返回(双)((总和/计数)-最小值)/最大-最小值;
}

当我这样做时,他们说流已经通过管道传输。

您应该将流传输到一个有序的集合中,并在一次迭代中获得诸如最大值、最小值和计数等信息(第一个元素、最后一个元素、集合的大小) 然后,您可以再次调用.stream().sum()来查找总和

因此:

    import java.util.*;
import java.util.stream.*;

public class Test{

    public static void main(String[] args) {
        System.out.println(normalizedStream(Stream.of(1, 2, 3, 4, 5)));
    }

    public static double normalizedStream(Stream < Integer > stream) {
        List < Integer > sortedList = stream.sorted().collect(Collectors.toList());
        Integer max = sortedList.get(sortedList.size() - 1);
        Integer min = sortedList.get(0);
        long count = sortedList.size();
        Integer sum = sortedList.stream().mapToInt(Integer::intValue).sum();
        return (double)((sum / count) - min) / (max - min);
    }
}
import java.util.*;
导入java.util.stream.*;
公开课考试{
公共静态void main(字符串[]args){
System.out.println(normalizedStream(Stream.of(1,2,3,4,5));
}
公共静态双规范化流(流<整数>流){
ListsortedList=stream.sorted().collect(Collectors.toList());
整数max=sortedList.get(sortedList.size()-1);
整数min=sortedList.get(0);
长计数=sortedList.size();
整数和=sortedList.stream().mapToInt(整数::intValue).sum();
返回(双)((总和/计数)-最小值)/最大-最小值;
}
}

您不能多次使用单个流,因此您必须创建流的副本,或者通过使用单个缩减操作获得您需要的所有统计数据(平均、最大、最小)

对于前一种方法,您需要知道流的来源,即某种
供应商
,每次调用
get
,都会给您一个新流,并多次调用:

// Rather than passing in someList.stream(), you would instead pass in someList::stream, for example
public static double normalizedMean(Supplier<Stream<Integer>> streamSupplier) {
    Integer max = max(streamSupplier.get());
    Integer min = min(streamSupplier.get());
    Integer sum = sum(streamSupplier.get());
    long count = count(streamSupplier.get());
    return (double) ((sum / count) - min) / (max - min);
}
我还建议您只使用
IntStream
。这样可以避免装箱/拆箱,只需执行以下操作:

var stats = stream.summaryStatistics();
从无到有的lambda解决方案可以作为没有准备好的内置收集器的问题的蓝图

公共静态双规范化平均值(流整数){
int[]min={Integer.MAX_VALUE};
int[]max={Integer.MIN_VALUE};
长[]计数={1};
返回整数收集(收集然后减少)(a,b)->{
min[0]=min[0]==Integer.MAX_值?min(a,b):min(min[0],b);
max[0]=max[0]==Integer.MIN_值?max(a,b):max(max[0],b);
计数[0]++;
返回(a+b);
}),m->(((double)m.get())/count[0]-min[0])/(max[0]-min[0]);
}
如果
normalizedMean()
不是
静态的

min
max
count
可以定义为标量类变量

int-min
int max
长计数

,因为它有。您需要使用自己的聚合器获取当前最大值、最小值和运行总和。流不是集合。这是一个元素流。它有一个源和一个输出。当输出请求下一个元素时,流将一个元素沿着链从源传递到输出。它不会存储通过流的每个元素。如果你想知道前面的元素是什么,你必须自己存储它们。一个流一旦被使用就不能再被使用。因此,不能使用相同的流来查找最小值、最大值、太阳和计数。这些操作中只有一个可以在流上工作。@dhruvtailor。当然可以。你只要自己做就行了,不。无法再次使用同一个流实例。计算最大元素时使用流。之后,该流将无法使用。您必须创建一个新的流实例@在将流传输到集合上的有序collectionCall stream以计算总和之后,我不认为我可以再次调用流。不是原始流。回答得好。向上投票。您还可以使用stream.collect(Collectors.summaringit(i->i))获得IntSummaryStatistics结果。
var stats = stream.summaryStatistics();
public static double normalizedMean(Stream<Integer> ints) {
  int[] min = {Integer.MAX_VALUE};
  int[] max = {Integer.MIN_VALUE};
  long[] count = {1};
  return ints.collect(collectingAndThen(reducing((a, b) -> {
    min[0] = min[0] == Integer.MAX_VALUE ? min(a, b) : min(min[0], b);
    max[0] = max[0] == Integer.MIN_VALUE ? max(a, b) : max(max[0], b);
    count[0]++;
    return(a + b);
  }), m -> (((double)m.get()) / count[0] - min[0]) / (max[0] - min[0])));
}