java 统计集合中对象的不特定字段的平均值

动态统计某字段

图片说明

 private RecordLevelModel getRecordLevelModel(Map.Entry<Integer, List<EsFitnessTestRecordDO>> entry, List<EsFitnessTestRecordDO> projectAndSexList) {
        RecordLevelModel bmiMaleModel = new RecordLevelModel().setGradeNumber(entry.getKey());
        Integer bmiUrbanMaleTotal = projectAndSexList.size();
        Map<String,Long> bmiMaleMap =  projectAndSexList.stream().collect(
                Collectors.groupingBy(EsFitnessTestRecordDO::getBmiRating,Collectors.counting()));
        for(Map.Entry<String,Long> entry1 : bmiMaleMap.entrySet())
        {
            LevelAndRegionModel levelAndRegionModel = new LevelAndRegionModel();
            double rate = entry1.getValue()/bmiUrbanMaleTotal;
            levelAndRegionModel.setLevelName(entry1.getKey()).setRate(rate).setTotal(Integer.parseInt(entry1.getValue().toString()));
            bmiMaleModel.getLevelModelList().add(levelAndRegionModel);
        }
        String projectName = "";
        Class<EsFitnessTestRecordDO> clz = EsFitnessTestRecordDO.class;
        try {
            String methodName = "get"+projectName;
            Method method = EsFitnessTestRecordDO.class.getMethod(methodName);
            double ave =  projectAndSexList.stream().mapToDouble(method).average().average().getAsDouble();
            double average = projectAndSexList.stream().mapToDouble(EsFitnessTestRecordDO::getBmi).average().getAsDouble();
        }catch (NoSuchMethodException e){
        }
        return bmiMaleModel;
    }

写了动态指定单个字段的分组,但是 MethodHandle handle = lookup.findGetter(this.getT().getClass(), fieldName, String.class); 会报错找不到字段,我确定字段没写错

public class CollectionsUtils<T> {

    private T t;

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    public CollectionsUtils(T t) {
        this.t = t;
    }

    //多字段排序
    public   <T> Map<List<String>, List<T>> DynamicGroupListByFiled(List<T> data, String[] groupByFieldNames) {
        final MethodHandles.Lookup lookup = MethodHandles.lookup();
        List<MethodHandle> handles =
                Arrays.stream(groupByFieldNames)
                        .map(field -> {
                            try {
                                return lookup.findGetter(this.getT().getClass(), field, String.class);
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        }).collect(Collectors.toList());
        return data.stream().collect(Collectors.groupingBy(
                d -> handles.stream()
                        .map(handle -> {
                            try {
                                return (String) handle.invokeExact(d);
                            } catch (Throwable e) {
                                throw new RuntimeException(e);
                            }
                        }).collect(Collectors.toList())
        ));
    }

    //按某字段分组后统计数量
    public   Map<String, Long> DynamicGroupListByFiled(List<T> data, String fieldName) {
        final MethodHandles.Lookup lookup = MethodHandles.lookup();
        try {
            MethodHandle handle = lookup.findGetter(this.getT().getClass(), fieldName, String.class);
            return data.stream().collect(Collectors.groupingBy(
                    d -> {
                        try {
                            return (String) handle.invokeExact(d);
                        } catch (Throwable e) {
                            throw new RuntimeException(e);
                        }
                    } ,Collectors.counting()));
        }
        catch (Throwable e)
        {
            throw new RuntimeException();
        }


    }

    //算不定字段平均值
    public    Double getDynamicFieldAverage(List<T> data, String fieldName) {
        final MethodHandles.Lookup lookup = MethodHandles.lookup();
        try {
            MethodHandle handle = lookup.findGetter(this.getT().getClass(), fieldName, String.class);
            return  data.stream().mapToDouble(d -> {
                        try {
                            return (Double) handle.invokeExact(d);
                        } catch (Throwable e) {
                            throw new RuntimeException(e);
                        }
                    }
            ).average().getAsDouble();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

         @Test
   public void testCollectionUtils()
   {
       List<EsFitnessTestRecordDO> list = new ArrayList<>();
       list.add(new EsFitnessTestRecordDO().setBmiRating("优秀").setBmiScore(90D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("优秀").setBmiScore(92D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("优秀").setBmiScore(94D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("良好").setBmiScore(80D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("良好").setBmiScore(82D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("良好").setBmiScore(84D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("合格").setBmiScore(70D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("合格").setBmiScore(76D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("不合格").setBmiScore(50D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("不合格").setBmiScore(40D));
       list.add(new EsFitnessTestRecordDO().setBmiRating("不合格").setBmiScore(30D));
       CollectionsUtils<EsFitnessTestRecordDO> ct = new CollectionsUtils(EsFitnessTestRecordDO.class);
    //统计bmiRating字段 优秀、良好、合格、不合格的各自人数,bmiRating是传递的参数
       Map<String, Long> map =  ct.DynamicGroupListByFiled(list,"bmiRating");
    //计算bmiScore字段的平均值,bmiScore是传递的动态参数
       double bmiAverage = ct.getDynamicFieldAverage(list,"bmiScore");
   }

类的字段
调试bug图
BUG

你光贴图片,没办法在上面给你改,但是,你可以把getBmiRating那里换成反射获取某个列的值。

以前用C#写过类似的程序,你看看是不是要这个效果:
https://ask.csdn.net/questions/703207

这里有一个java stream动态分组的代码:

private static Map<List<String>, List<MyClass>> groupListBy(List<MyClass> data, String[] groupByFieldNames) {
    final MethodHandles.Lookup lookup = MethodHandles.lookup();
    List<MethodHandle> handles = 
        Arrays.stream(groupByFieldNames)
              .map(field -> {
                  try {
                      return lookup.findGetter(MyClass.class, field, String.class);
                  } catch (Exception e) {
                      throw new RuntimeException(e);
                  }
              }).collect(toList());
    return data.stream().collect(groupingBy(
            d -> handles.stream()
                        .map(handle -> {
                            try {
                                return (String) handle.invokeExact(d);
                            } catch (Throwable e) {
                                throw new RuntimeException(e);
                            }
                        }).collect(toList())
        ));
}

同样的思路做动态取平均值也是一样的。