Java 方法生成重复代码。如何简化?

Java 方法生成重复代码。如何简化?,java,java-stream,Java,Java Stream,我正在学习Java,我将不得不为一个大学项目做一个项目 public double getCreditAmount() { return movementList.stream() .filter(s -> s.getDate().before(tomorrow())) .filter(s -> s.type() == MovementType.CREDIT) .mapToDouble(s -&g

我正在学习Java,我将不得不为一个大学项目做一个项目

    public double getCreditAmount() {
    return movementList.stream()
            .filter(s -> s.getDate().before(tomorrow()))
            .filter(s -> s.type() == MovementType.CREDIT)
            .mapToDouble(s -> s.amount())
            .reduce(Double::sum)
            .orElse(0.0);
}

public double getDebitAmount(){
    return movementList.stream()
            .filter(s -> s.getDate().before(tomorrow()))
            .filter(s -> s.type() == MovementType.DEBIT)
            .mapToDouble(s -> s.amount())
            .reduce(Double::sum)
            .orElse(0.0);
}

public double updateBalance(){
    return sumOfTotal = getCreditAmount()-getDebitAmount();
}
这是我的代码,它使用枚举(借方或贷方)添加当前值​​updateBalance方法将它们相互减去。 但我明白,这种方式会产生重复的代码,我可以以某种方式避免。 如何避免重复代码?
我知道我应该创建一个更通用的方法,避免重复getCreditAmount()和getDebitAmount()的代码。但是我该怎么做呢?

因为唯一的区别是
MovementType
值,所以将其作为一个参数:

public double getAmount(MovementType type) {
    return movementList.stream().filter(s -> s.getDate().before(tomorrow()))
                       .filter(s -> s.type() == type).mapToDouble(s -> s.amount())
                       .reduce(Double::sum).orElse(0.0);
}
并像这样使用(不需要中间
sumOfTotal
变量)


只需实现一种方法并将
MovementType
作为参数传递:

public double getAmount(MovementType movementType) {
    return movementList.stream()
            .filter(s -> s.getDate().before(tomorrow()))
            .filter(s -> s.type() == movementType)
            .mapToDouble(s -> s.amount())
            .reduce(Double::sum)
            .orElse(0.0);
}

public double updateBalance() {
    return getAmount(MovementType.CREDIT) - getAmount(MovementType.DEBIT);
}
一个有效的替代方法是定义一个额外的
getBalanceAmount()
方法,该方法一次完成所有操作。这样可以避免必须对列表进行两次流式处理:

public double getBalanceAmount(){
    return movementList.stream()
            .filter(s -> s.getDate().before(tomorrow()))
            .mapToDouble(s -> s.amount() * (s.type() == MovementType.DEBIT ? -1 : 1)
            .reduce(Double::sum)
            .orElse(0.0);
}

正如其他人所说,您可以将运动类型作为参数传递,这遵循了编码中的一个关键原则:干燥(不要重复)

您需要做的其他事情:

  • 给你的方法一个通用名称,因为它现在支持两个操作:贷记和借记,例如get、fetch和compute。我选择compute是因为我们正在用这种方法进行一些计算
  • 我关心您在mapToDouble中所做的事情,因为它是一个中间操作,返回一个DoubleStream,其中包含将给定映射器函数应用于该流元素的结果。所以我假设s.amount()没有返回一个double,所以我将amount(s.amount())传递给double::parseDouble,以将输入解析为double值
  • 下面是我将如何处理这个问题

    public double computeAmount(MovementType type) {
        return movementList.stream()
                .filter(s -> s.getDate().before(tomorrow()))
                .filter(s -> s.type() == type)
                .mapToDouble(s -> Double::parseDouble(s.amount()))
                .reduce(Double::sum)
                .orElse(0.0);
    }
    
    public double updateBalance(){
        return computeAmount(MovementType.CREDIT) - computeAmount(MovementType.DEBIT); 
    }
    

    我很惊讶你写了这样的代码,却不知道参数,或者它不是你的代码?方法中的参数比这更基本code@azro-他在学习。(事实上,很高兴看到一些Unis现在正在教授Java流。)@StephenC right。在此期间,我们通过以下方式学习编程:streams@azro编写的代码是我纯粹的幻想和创造。我只是没有考虑过这种类型的解决方案,可能是因为我有点粗心,也可能是出于无知,因为我不太擅长编程。谢谢你这么快的回复。我没有想到采用MovementType参数的解决方案。非常感谢。祝您有一个愉快的一天。@acata8您现在可以考虑或评论其中一个以获取详细信息;)奖励那些为你付出时间的人;)多亏了及时的反应。我相信我会选择两种不同的解决方法。然而,我有很好的直觉。非常感谢。祝您度过愉快的一天,除非您确信s.amount()返回一个字符串,否则您可以使用以前的字符串删除Double::parseDouble。您可以使用评论或接受回答进一步提问。感谢您的即时回复。s、 amount()返回一个双精度值。我是否需要使用Double::parseDouble?你认为我可以简单地使用.map()还是需要使用.mapToDouble()?是的。在这种情况下不需要mapToDouble。注意,如果compute/getAmount方法在类外不可访问,则可以提供该方法。这叫做封装。感谢的关键原则。我会考虑你的建议。
    public double computeAmount(MovementType type) {
        return movementList.stream()
                .filter(s -> s.getDate().before(tomorrow()))
                .filter(s -> s.type() == type)
                .mapToDouble(s -> Double::parseDouble(s.amount()))
                .reduce(Double::sum)
                .orElse(0.0);
    }
    
    public double updateBalance(){
        return computeAmount(MovementType.CREDIT) - computeAmount(MovementType.DEBIT); 
    }