当前位置: 首页 > 面试题库 >

如何汇总对象列表的各个字段并以单个对象的形式返回结果

齐航
2023-03-14
问题内容

我有一种方法可以为从API请求调用中接收到的对象列表计算营养素。

该方法如下所示:

public Nutrients nutrientsCalculator(DailyMeals dailyMeals) {

    String foodNamesForRequest = prepareFoodNamesForRequest(dailyMeals);

    HttpEntity<NutrientsBodyForRequest> requestBody = prepareRequestForAPICall(foodNamesForRequest);

    ResponseEntity<List<FoodNutritional>> response =
        //create request here

    if (nonNull(response.getBody())) {

      double totalFat = response.getBody()
          .stream()
          .map(FoodNutritional::getTotalFat)
          .mapToDouble(Double::doubleValue)
          .sum();

      double totalProtein = response.getBody()
          .stream()
          .map(FoodNutritional::getProtein)
          .mapToDouble(Double::doubleValue)
          .sum();

      double totalCarbohydrates = response.getBody()
          .stream()
          .map(FoodNutritional::getTotalCarbohydrate)
          .mapToDouble(Double::doubleValue)
          .sum();

      double totalDietaryFiber = response.getBody()
          .stream()
          .map(FoodNutritional::getDietaryFiber)
          .mapToDouble(Double::doubleValue)
          .sum();

      return Nutrients.builder()
          .carbohydrates(totalCarbohydrates)
          .protein(totalProtein)
          .fat(totalFat)
          .dietaryFiber(totalDietaryFiber)
          .build();
    }
    return new Nutrients();
  }

我的FoodNutritional.class看起来像:

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
class FoodNutritional {

  @JsonProperty("food_name")
  private String foodName;

  @JsonProperty("brand_name")
  private String brandName;

  @JsonProperty("serving_qty")
  private Integer servingQuantity;

  @JsonProperty("serving_unit")
  private String servingUnit;

  @JsonProperty("serving_weight_grams")
  private String servingWeightGrams;

  @JsonProperty("nf_calories")
  private Double calories;

  @JsonProperty("nf_total_fat")
  private Double totalFat;

  @JsonProperty("nf_saturated_fat")
  private Double saturatedFat;

  @JsonProperty("nf_cholesterol")
  private Double cholesterol;

  @JsonProperty("nf_sodium")
  private Double sodium;

  @JsonProperty("nf_total_carbohydrate")
  private Double totalCarbohydrate;

  @JsonProperty("nf_dietary_fiber")
  private Double dietaryFiber;

  @JsonProperty("nf_sugars")
  private Double sugars;

  @JsonProperty("nf_protein")
  private Double protein;

  @JsonProperty("nf_potassium")
  private Double potassium;
}

我的方法解决方案可行,但我开始考虑是否有可能摆脱这种sum流方法的样板。

我要实现的是汇总单个字段:totalFat,,proteindietaryFibertotalCarbohydrate并将它们作为新对象的components字段返回

我将很高兴为您提供有关如何提高当前版本代码质量的建议。

编辑:

在周末,我花了一点时间找到一种可以满足要求并且功能更多的其他方法。最后,我创建了两个静态方法,例如:

private static Nutrients reduceNutrients(Nutrients n1, Nutrients n2) {
    return Nutrients.builder()
        .protein(n1.getProtein() + n2.getProtein())
        .carbohydrates(n1.getCarbohydrates() + n2.getCarbohydrates())
        .dietaryFiber(n1.getDietaryFiber() + n2.getDietaryFiber())
        .fat(n1.getFat() + n2.getFat())
        .build();
  }

  private static Nutrients fromFoodNutritionalToNutrients(FoodNutritional foodNutritional) {
    return Nutrients.builder()
        .dietaryFiber(foodNutritional.getDietaryFiber())
        .carbohydrates(foodNutritional.getTotalCarbohydrate())
        .fat(foodNutritional.getTotalFat())
        .protein(foodNutritional.getProtein())
        .build();
  }

毕竟我像这样使用它:

Stream<FoodNutritional> foodNutritionalStream = Optional.ofNullable(response.getBody()).stream()
        .flatMap(List::stream);

Nutrients nutrients = foodNutritionalStream
        .map(NutrientsCalculatorService::fromFoodNutritionalToNutrients)
        .reduce(NutrientsCalculatorService::reduceNutrients)
        .orElseThrow(() -> new CustomException("custom_exception");

尽管如此,为@Koziołek@Nir Levy@Naman成为我的缪斯女士致以问候。感谢您的每一个承诺。


问题答案:

让我们介绍一下课程NutritionAccumulator

class NutritionAccumulator{
    private double fat = 0.;
    private double carbs = 0.;
    private double fiber = 0.;
    private double protein = 0.;

    public NutritionAccumulator() {
    }

    public NutritionAccumulator(double fat, double carbs, double fiber, double protein) {
        this.fat = fat;
        this.carbs = carbs;
        this.fiber = fiber;
        this.protein = protein;
    }

    public NutritionAccumulator add(NutritionAccumulator that){
        return new NutritionAccumulator(this.fat + that.fat,
        this.carbs + that.carbs,
        this.fiber + that.fiber,
        this.protein + that.protein
        );
    }
}

现在我们可以编写简单的stream reduce:

Optional.ofNullable(response.body())
.stream()
.reduce(
                        new NutritionAccumulator(),
                        (acc, fudNut) -> new NutritionAccumulator(
                                fudNut.getTotalFat(),
                                fudNut.getTotalCarbohydrate(),
                                fudNut.getDietaryFiber(),
                                fudNut.getProtein()
                        ).add(acc),
                        NutritionAccumulator::add

                );

最后,您可以将结果从上方传递给生成器。



 类似资料:
  • 我有一个包含多个字段和两个对象的列表,我的要求是形成一个

  • 我对Spring编程是新手。我正在用Reactor/Webflux项目测试反应式编程。 数据库注册通过POST工作得很好。 我的模型: 我的存储库 我的用户服务

  • 问题内容: 当使用平滑功能时,如何在返回一个更新的表的同时更新一个表中的几列? 假设SomeTables有一些TableQuery,例如,如果您想向表中添加一个项目(并返回新添加的项目),通常会编写这样的查询 如果您要更新商品并将整个商品退回整个商品,该怎么做,我怀疑您会做这样的事情 但是,以下代码不起作用,并且我看不到任何有关如何执行此操作的文档 请注意,我知道您可以事先查询该项目,对其进行更新

  • 我使用mysql存储过程来检索对象列表。这可能吗? 我在看这篇文章 问题: > 如何使用结果集检索select语句中的对象列表? 如何将结果集映射到对象列表? CREATE DEFINER=@PROCEDURE(ININT,OUTINT,OUTINT,OUTVARCHAR(50),OUTVARCHAR(50),OUTFLOAT 内部连接(从rate中选择aid,r.rate,re.country_

  • 我有如下代码: 我想将上述代码按照 level 字段划分,改造成如下格式 层级可能不限于 3 级,所以我能想到的是使用递归,但是尝试写了几遍均已失败告终 还望解答,万分感谢!