Java 8 如何获得多属性';使用java8流的平均值是多少?

Java 8 如何获得多属性';使用java8流的平均值是多少?,java-8,java-stream,Java 8,Java Stream,有一个物体 @Data class ScoreInfo{ String id; float cove_score; float theam_score; float content_score; float teach_score; Date create_date; ScoreInfoP scoreInfoP; } ScoreInfoP是: @Data class ScoreInfoP{ String stream_sn; String anchor_id; String crea

有一个物体

@Data
class ScoreInfo{
String id;

float cove_score;
float theam_score;
float content_score;
float teach_score;

Date create_date;
ScoreInfoP scoreInfoP;
}

ScoreInfoP是:

@Data
class ScoreInfoP{

String stream_sn;

String anchor_id;

String create_by;
}
sourceList是ScoreInfo的列表,我想获得cove_分数、theam_分数、content_分数、teach_分数的平均值、group by scoreInfoP属性并为每个属性返回四个平均值

使用这样的代码,我只能得到一个平均值:

Map<ScoreInfoP, Double> meanForCoveScore = sourceList.stream().collect(Collectors.groupingBy(ScoreInfo::getScoreInfoP,
            Collectors.averagingDouble(ScoreInfo::getCove_score)));
Map meansforcovescore=sourceList.stream().collect(收集器.groupingBy(ScoreInfo::getScoreInfoP、,
收集器.averagingDouble(ScoreInfo::getCove_score));
我想学习如何使用java8或您建议的任何更简单的方法获得四个平均值


在这里等待您的慷慨帮助。

没有任何内置功能,但为其构建自定义收集器并不复杂

 Map<String, List<Float>> result = Arrays.asList(first, second)
            .stream()
            .collect(Collectors.groupingBy(
                    x -> x.getScoreInfoP().getAnchorId(), 
                    Collector.of(
                            () -> new float[5],
                            (a, x) -> {
                                a[0] += x.getCoveScore();
                                a[1] += x.getTheamScore();
                                a[2] += x.getTeachScore();
                                a[3] += x.getContentScore();
                                a[4]++;
                            },

                            (left, right) -> {
                                for (int i = 0; i < 4; ++i) {
                                    left[i] += right[i];
                                }

                                return left;
                            }, x -> Arrays.asList(x[0] / x[4], x[1] / x[4], x[2] / x[4], x[3] / x[4]))

    ));

    System.out.println(result);
Map result=Arrays.asList(第一、第二)
.stream()
.collect(收集器.groupingBy(
x->x.getScoreInfoP().getAnchorId(),
收藏(
()->新浮点数[5],
(a,x)->{
a[0]+=x.getCoveScore();
a[1]+=x.gettheamcore();
a[2]+=x.getTeachScore();
a[3]+=x.getContentScore();
a[4]++;
},
(左,右)->{
对于(int i=0;i<4;++i){
左[i]+=右[i];
}
左转;
},x->Arrays.asList(x[0]/x[4],x[1]/x[4],x[2]/x[4],x[3]/x[4]))
));
系统输出打印项次(结果);

实际上,我是在
ScoreInfoP#anchorId
上进行分组的;但您可以在
ScoreInfoP
上执行此操作-为此,您需要将
x->x.getScoreInfoP().getAnchorId()
更改为
x->x.getScoreInfoP()
。但是显然,
ScoreInfoP
需要覆盖
hashCode
equals
没有任何内置功能,但是为其构建自定义收集器并不复杂

 Map<String, List<Float>> result = Arrays.asList(first, second)
            .stream()
            .collect(Collectors.groupingBy(
                    x -> x.getScoreInfoP().getAnchorId(), 
                    Collector.of(
                            () -> new float[5],
                            (a, x) -> {
                                a[0] += x.getCoveScore();
                                a[1] += x.getTheamScore();
                                a[2] += x.getTeachScore();
                                a[3] += x.getContentScore();
                                a[4]++;
                            },

                            (left, right) -> {
                                for (int i = 0; i < 4; ++i) {
                                    left[i] += right[i];
                                }

                                return left;
                            }, x -> Arrays.asList(x[0] / x[4], x[1] / x[4], x[2] / x[4], x[3] / x[4]))

    ));

    System.out.println(result);
Map result=Arrays.asList(第一、第二)
.stream()
.collect(收集器.groupingBy(
x->x.getScoreInfoP().getAnchorId(),
收藏(
()->新浮点数[5],
(a,x)->{
a[0]+=x.getCoveScore();
a[1]+=x.gettheamcore();
a[2]+=x.getTeachScore();
a[3]+=x.getContentScore();
a[4]++;
},
(左,右)->{
对于(int i=0;i<4;++i){
左[i]+=右[i];
}
左转;
},x->Arrays.asList(x[0]/x[4],x[1]/x[4],x[2]/x[4],x[3]/x[4]))
));
系统输出打印项次(结果);

实际上,我是在
ScoreInfoP#anchorId
上进行分组的;但您可以在
ScoreInfoP
上执行此操作-为此,您需要将
x->x.getScoreInfoP().getAnchorId()
更改为
x->x.getScoreInfoP()
。但是很明显,
ScoreInfoP
需要覆盖
hashCode
equals
,正如我在评论中所说的,您应该使用适当的结果类

class ScoreInfoAverage {
  private float cove_score;
  private float theam_score;
  private float content_score;
  private float teach_score;

  // ctor, getter, setter
}

然后您可以使用自定义的
收集器

public static Collector<ScoreInfo, ?, ScoreInfoAverage> scoreInfoToAverage() {
  class ScoreInfoAccumulator {
    private DoubleSummaryStatistics cove_score = new DoubleSummaryStatistics();
    private DoubleSummaryStatistics theam_score = new DoubleSummaryStatistics();
    private DoubleSummaryStatistics content_score = new DoubleSummaryStatistics();
    private DoubleSummaryStatistics teach_score = new DoubleSummaryStatistics();

    public void add(ScoreInfo si) {
      cove_score.accept(si.cove_score);
      theam_score.accept(si.theam_score);
      content_score.accept(si.content_score);
      teach_score.accept(si.teach_score);
    }

    public ScoreInfoAccumulator combine(ScoreInfoAccumulator sia) {
      cove_score.combine(sia.cove_score);
      theam_score.combine(sia.theam_score);
      content_score.combine(sia.content_score);
      teach_score.combine(sia.teach_score);
      return this;
    }

    public ScoreInfoAverage average() {
      return new ScoreInfoAverage((float) cove_score.getAverage(), 
        (float) theam_score.getAverage(), (float) content_score.getAverage(), 
        (float) teach_score.getAverage());
    }
  }
  return Collector.of(ScoreInfoAccumulator::new, ScoreInfoAccumulator::add, 
        ScoreInfoAccumulator::combine, ScoreInfoAccumulator::average);
}

正如我在评论中所说的,您应该使用适当的结果类

class ScoreInfoAverage {
  private float cove_score;
  private float theam_score;
  private float content_score;
  private float teach_score;

  // ctor, getter, setter
}

然后您可以使用自定义的
收集器

public static Collector<ScoreInfo, ?, ScoreInfoAverage> scoreInfoToAverage() {
  class ScoreInfoAccumulator {
    private DoubleSummaryStatistics cove_score = new DoubleSummaryStatistics();
    private DoubleSummaryStatistics theam_score = new DoubleSummaryStatistics();
    private DoubleSummaryStatistics content_score = new DoubleSummaryStatistics();
    private DoubleSummaryStatistics teach_score = new DoubleSummaryStatistics();

    public void add(ScoreInfo si) {
      cove_score.accept(si.cove_score);
      theam_score.accept(si.theam_score);
      content_score.accept(si.content_score);
      teach_score.accept(si.teach_score);
    }

    public ScoreInfoAccumulator combine(ScoreInfoAccumulator sia) {
      cove_score.combine(sia.cove_score);
      theam_score.combine(sia.theam_score);
      content_score.combine(sia.content_score);
      teach_score.combine(sia.teach_score);
      return this;
    }

    public ScoreInfoAverage average() {
      return new ScoreInfoAverage((float) cove_score.getAverage(), 
        (float) theam_score.getAverage(), (float) content_score.getAverage(), 
        (float) teach_score.getAverage());
    }
  }
  return Collector.of(ScoreInfoAccumulator::new, ScoreInfoAccumulator::add, 
        ScoreInfoAccumulator::combine, ScoreInfoAccumulator::average);
}


你的意思是得到每个平均值吗?最优雅的方法是创建一个结果类。@holi java是的,我想得到四个平均值values@Flown我可以详细地问你怎么做吗..但是4个平均值的类型不是
Map
,它应该是
Map
。你的意思是获取每个平均值吗?最优雅的方法是创建一个结果类。@holi java是的,我想获取四个平均值values@Flown我可以详细地问你怎么做吗..但是4个平均值的类型不是
Map
,它应该是
Map
。我觉得有点太多了。。。你可以简单地把它们加起来,然后再分;与普通的
收集器几乎相同。平均值…
does@Eugene为什么要一次又一次地重新发明轮子?我不理解你的评论honest@Eugene你指的是双重总和统计,对吧?那么,既然JDK中已经有了经过测试的功能,我为什么还要在以后添加和划分呢?哦,对了——这对我的口味来说可能太多了,而且我觉得可读性较差——但这里可能是我。另外,你也有一个观点(不确定你是否知道)-你的解决方案使用了Kahan求和,它比简单的加法/除法做得更好。。。你可以简单地把它们加起来,然后再分;与普通的
收集器几乎相同。平均值…
does@Eugene为什么要一次又一次地重新发明轮子?我不理解你的评论honest@Eugene你指的是双重总和统计,对吧?那么,既然JDK中已经有了经过测试的功能,我为什么还要在以后添加和划分呢?哦,对了——这对我的口味来说可能太多了,而且我觉得可读性较差——但这里可能是我。另外,这里也有一点(不确定您是否知道)-您的解决方案使用Kahan求和,比简单的加法/除法更能进行舍入。我使用Lombok,带有数据注释,不需要提供hashcode和equals。我用你的模板修改了我的代码,它失败了。但我认为你的清晰方法是正确的,我需要学习它并找出它失败的原因。它现在编译成功了。现在我没有数据要测试,我没有