Java 8重构lambda表达式

Java 8重构lambda表达式,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,我想使用lambda表达式创建一个应用公共统计信息的简单类。 我想知道如何避免在statistic()方法中使用switch case 例如,我可能想编写一个新的lambda来计算列表的方差,等等 多谢各位 public class DescriptiveStatistics { public static void main(String[] args) { List<Double> numbers = Arrays.asList(1.0, 2.0, 3.

我想使用lambda表达式创建一个应用公共统计信息的简单类。 我想知道如何避免在statistic()方法中使用switch case

例如,我可能想编写一个新的lambda来计算列表的方差,等等

多谢各位

public class DescriptiveStatistics {

    public static void main(String[] args) {
        List<Double> numbers = Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0);
        numbers.stream().forEach(n-> System.out.print(n + " "));
        System.out.println();
        System.out.println("Descriptive statistics");
        System.out.println("Sum: " + statistic(numbers, "Sum"));
        System.out.println("Max: " + statistic(numbers, "Max"));
        System.out.println("Min: " + statistic(numbers, "Min"));
        System.out.println("Average: " + statistic(numbers, "Average"));
        System.out.println("Count: " + statistic(numbers, "Count"));
    }

    private static double statistic(List<Double> numbers, String function) {
        switch (function.toLowerCase()) {
            case "sum":
                return numbers.stream().mapToDouble(Double::doubleValue).sum();
            case "max":
                return numbers.stream().mapToDouble(Double::doubleValue).max().getAsDouble();
            case "min":
                return numbers.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
            case "average":
                return numbers.stream().mapToDouble(Double::doubleValue).average().getAsDouble();
            case "count":
                return numbers.stream().mapToDouble(Double::doubleValue).count();
        }
        return 0;
    }
公共类描述统计学{
公共静态void main(字符串[]args){
列表编号=数组.asList(1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0);
numbers.stream().forEach(n->System.out.print(n+);
System.out.println();
System.out.println(“描述性统计”);
System.out.println(“总和:+统计(数字,“总和”));
System.out.println(“Max:+统计(数字,“Max”));
System.out.println(“Min:+统计(数字,“Min”));
System.out.println(“平均:”+统计(数字,“平均”));
System.out.println(“计数:”+统计(数字,“计数”));
}
私有静态双重统计(列表编号、字符串函数){
开关(function.toLowerCase()){
案例“金额”:
返回numbers.stream().mapToDouble(Double::doubleValue.sum();
案例“max”:
返回numbers.stream().mapToDouble(Double::doubleValue.max().getAsDouble();
案例“min”:
返回numbers.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
案例“平均值”:
返回numbers.stream().mapToDouble(Double::doubleValue).average().getAsDouble();
案例“计数”:
返回numbers.stream().mapToDouble(Double::doubleValue.count();
}
返回0;
}
我想到了这样一种方法

private static double newStatistics(List<Double> numbers, Function<Double, Double> function){
        return  numbers.stream().mapToDouble(Double::doubleValue).function();
    }
private静态双新闻统计(列表编号、函数){
返回numbers.stream().mapToDouble(Double::doubleValue.function();
}
将方法统计的字符串参数替换为函数类型,该函数类型接受DoubleStream并返回聚合

private static double statistic(List<Double> numbers,
                                ToDoubleFunction<DoubleStream> function) {
    return function.applyAsDouble(
        numbers.stream().mapToDouble(Double::doubleValue));
}
为什么不简单地使用或应用类似的模式

您甚至可以扩展该类以添加自定义方法,例如方差、偏度和峰度,例如:

/**
 * Algorithms derived from: Philippe Pébay, Formulas for Robust, One-Pass Parallel
 * Computation of Covariances and Arbitrary-Order Statistical Moments.
 */
public class MoreDoubleStatistics extends DoubleSummaryStatistics {

    private double M1, M2, M3, M4;

    @Override
    public void accept(double x) {
        super.accept(x);

        long n = getCount();

        double delta = x - M1;                       // δ
        double delta_n = delta / n;                  // δ / n
        double delta2_n = delta * delta_n;           // δ^2 / n
        double delta2_n2 = delta_n * delta_n;        // δ^2 / n^2
        double delta3_n2 = delta2_n * delta_n;       // δ^3 / n^2
        double delta4_n3 = delta3_n2 * delta_n;      // δ^4 / n^3

        M4 += (n - 1) * (n * n - 3 * n + 3) * delta4_n3
                + 6 * M2 * delta2_n2
                - 4 * M3 * delta_n;
        M3 += (n - 1) * (n - 2) * delta3_n2
                - 3 * M2 * delta_n;
        M2 += (n - 1) * delta2_n;
        M1 += delta_n;
    }

    @Override
    public void combine(DoubleSummaryStatistics other) {
      throw new UnsupportedOperationException(
              "Can't combine a standard DoubleSummaryStatistics with this class");
    }

    public void combine(MoreDoubleStatistics other) {
        MoreDoubleStatistics s1 = this;
        MoreDoubleStatistics s2 = other;

        long n1 = s1.n();
        long n2 = s2.n();
        long n = n1 + n2;

        double delta = s2.M1 - s1.M1;                // δ
        double delta_n = delta / n;                  // δ / n
        double delta2_n = delta * delta_n;           // δ^2 / n
        double delta2_n2 = delta_n * delta_n;        // δ^2 / n^2
        double delta3_n2 = delta2_n * delta_n;       // δ^3 / n^2
        double delta4_n3 = delta3_n2 * delta_n;      // δ^4 / n^3

        this.M4 = s1.M4 + s2.M4 + n1 * n2 * (n1 * n1 - n1 * n2 + n2 * n2) * delta4_n3
                + 6.0 * (n1 * n1 * s2.M2 + n2 * n2 * s1.M2) * delta2_n2
                + 4.0 * (n1 * s2.M3 - n2 * s1.M3) * delta_n;

        this.M3 = s1.M3 + s2.M3 + n1 * n2 * (n1 - n2) * delta3_n2
                + 3.0 * (n1 * s2.M2 - n2 * s1.M2) * delta_n;

        this.M2 = s1.M2 + s2.M2 + n1 * n2 * delta2_n;

        this.M1 = s1.M1 + n2 * delta;

        super.combine(other);
    }

    private long n() { return getCount(); }

    public double mean() { return getAverage(); }
    public double variance() { return n() <= 1 ? 0 : M2 / (n() - 1); }
    public double stdDev() { return sqrt(variance()); }
    public double skew() { return M2 == 0 ? 0 : sqrt(n()) * M3/ pow(M2, 1.5); }
    public double kurtosis() { return M2 == 0 ? 0 : n() * M4 / (M2 * M2) - 3.0; }
}
/**
*算法来源:Philippe Pébay,鲁棒性公式,一次并行
*协方差和任意阶统计矩的计算。
*/
公共类更多DoubleStatistics扩展了DoubleSummaryStatistics{
私人双M1、M2、M3、M4;
@凌驾
公共无效接受(双x){
super.accept(x);
long n=getCount();
双δ=x-M1;//δ
双δn=δ/n;//δ/n
双delta2\u n=delta*delta\u n;//δ^2/n
双delta2_n2=delta_n*delta_n;//δ^2/n^2
双delta3_n2=delta2_n*delta_n;//δ^3/n^2
双delta4_n3=delta3_n2*delta_n;//δ^4/n^3
M4+=(n-1)*(n*n-3*n+3)*三角洲
+6*M2*delta2_n2
-4*M3*delta\n;
M3+=(n-1)*(n-2)*三角洲3_n2
-3*M2*delta\n;
M2+=(n-1)*三角洲2_n;
M1+=δn;
}
@凌驾
公共void联合收割机(DoubleSummaryStatistics其他){
抛出新的UnsupportedOperationException(
“无法将标准DoubleSummaryStatistics与此类组合”);
}
公共无效联合收割机(其他){
moredouplestatistics s1=这个;
moredouplestatistics s2=其他;
长n1=s1.n();
长n2=s2.n();
长n=n1+n2;
双增量=s2.M1-s1.M1;//δ
双δn=δ/n;//δ/n
双delta2\u n=delta*delta\u n;//δ^2/n
双delta2_n2=delta_n*delta_n;//δ^2/n^2
双delta3_n2=delta2_n*delta_n;//δ^3/n^2
双delta4_n3=delta3_n2*delta_n;//δ^4/n^3
此点M4=s1.M4+s2.M4+n1*n2*(n1*n1-n1*n2+n2*n2)*三角洲
+6.0*(n1*n1*s2.M2+n2*n2*s1.M2)*三角洲2_n2
+4.0*(n1*s2.M3-n2*s1.M3)*δn;
该系数为1.M3=s1.M3+s2.M3+n1*n2*(n1-n2)*三角洲
+3.0*(n1*s2.M2-n2*s1.M2)*δn;
这1.M2=s1.M2+s2.M2+n1*n2*delta2\n;
这1.M1=s1.M1+n2*delta;
超级联合收割机(其他);
}
私有长n(){return getCount();}
公共双平均值(){return getAverage();}

public double variance(){return n()您应该使用
enum
(如果您提前知道所有函数)或策略接口(如果您需要能够在运行时插入新函数)。我认为策略界面回答了这个问题。谢谢!谢谢。我在哪里可以阅读更多关于创建我自己的ToDoubleFunction()?例如,用于计算方差的内容。您可以将其简化为
DoubleStream::sum
s->s.count()而不是
s.sum()
@bcsb1001:在我看来,
s->s.sum()
DoubleStream::sum更简单(关于可读性和可维护性)。你能为一个组合函数提供代码,这样这个类就可以用作收集器吗?但是最终结果中的方差偏斜和峰度难道不是错误的吗?我的意思是DoubleSummaryStatistics::combine没有考虑它们,或者我遗漏了什么?
/**
 * Algorithms derived from: Philippe Pébay, Formulas for Robust, One-Pass Parallel
 * Computation of Covariances and Arbitrary-Order Statistical Moments.
 */
public class MoreDoubleStatistics extends DoubleSummaryStatistics {

    private double M1, M2, M3, M4;

    @Override
    public void accept(double x) {
        super.accept(x);

        long n = getCount();

        double delta = x - M1;                       // δ
        double delta_n = delta / n;                  // δ / n
        double delta2_n = delta * delta_n;           // δ^2 / n
        double delta2_n2 = delta_n * delta_n;        // δ^2 / n^2
        double delta3_n2 = delta2_n * delta_n;       // δ^3 / n^2
        double delta4_n3 = delta3_n2 * delta_n;      // δ^4 / n^3

        M4 += (n - 1) * (n * n - 3 * n + 3) * delta4_n3
                + 6 * M2 * delta2_n2
                - 4 * M3 * delta_n;
        M3 += (n - 1) * (n - 2) * delta3_n2
                - 3 * M2 * delta_n;
        M2 += (n - 1) * delta2_n;
        M1 += delta_n;
    }

    @Override
    public void combine(DoubleSummaryStatistics other) {
      throw new UnsupportedOperationException(
              "Can't combine a standard DoubleSummaryStatistics with this class");
    }

    public void combine(MoreDoubleStatistics other) {
        MoreDoubleStatistics s1 = this;
        MoreDoubleStatistics s2 = other;

        long n1 = s1.n();
        long n2 = s2.n();
        long n = n1 + n2;

        double delta = s2.M1 - s1.M1;                // δ
        double delta_n = delta / n;                  // δ / n
        double delta2_n = delta * delta_n;           // δ^2 / n
        double delta2_n2 = delta_n * delta_n;        // δ^2 / n^2
        double delta3_n2 = delta2_n * delta_n;       // δ^3 / n^2
        double delta4_n3 = delta3_n2 * delta_n;      // δ^4 / n^3

        this.M4 = s1.M4 + s2.M4 + n1 * n2 * (n1 * n1 - n1 * n2 + n2 * n2) * delta4_n3
                + 6.0 * (n1 * n1 * s2.M2 + n2 * n2 * s1.M2) * delta2_n2
                + 4.0 * (n1 * s2.M3 - n2 * s1.M3) * delta_n;

        this.M3 = s1.M3 + s2.M3 + n1 * n2 * (n1 - n2) * delta3_n2
                + 3.0 * (n1 * s2.M2 - n2 * s1.M2) * delta_n;

        this.M2 = s1.M2 + s2.M2 + n1 * n2 * delta2_n;

        this.M1 = s1.M1 + n2 * delta;

        super.combine(other);
    }

    private long n() { return getCount(); }

    public double mean() { return getAverage(); }
    public double variance() { return n() <= 1 ? 0 : M2 / (n() - 1); }
    public double stdDev() { return sqrt(variance()); }
    public double skew() { return M2 == 0 ? 0 : sqrt(n()) * M3/ pow(M2, 1.5); }
    public double kurtosis() { return M2 == 0 ? 0 : n() * M4 / (M2 * M2) - 3.0; }
}