将几种方法结合到唯一的方法中。泛型

时间:2015-06-10 11:12:21

标签: java generics refactoring

与BigInteger相比,我有一些代码可以找出对不同数据类型(int,long,double)的操作的正确性。操作是一个数字的阶乘,直到结果与BigInteger相同。

问题是如何更改我的代码,使其更通用,更紧凑和干净?我怎么能得到唯一的方法,而不是4种不同的方法? 这种方法的逻辑与流程完全相同。

代码(不比较逻辑)是:

private static HashMap<BigInteger, BigInteger> bigIntegerFactorials = new HashMap<>();
private static BigInteger bigIntegerFactorial(BigInteger number) {
    if (number.equals(BigInteger.ONE)) {
        return BigInteger.ONE;
    }
    BigInteger result = bigIntegerFactorials.get(number);
    if (result == null) {
        result = number.multiply(bigIntegerFactorial(number.subtract(BigInteger.ONE)));
        bigIntegerFactorials.put(number, result);
    }
    return result;
}

private static HashMap<Integer, Integer> intFactorials = new HashMap<>();
private static int intFactorial(int number) {
    if (number == 1) {
        return 1;
    }
    Integer result = intFactorials.get(number);
    if (result == null) {
        result = number * intFactorial(number - 1);
        intFactorials.put(number, result);
    }
    return result;
}

private static HashMap<Long, Long> longFactorials = new HashMap<>();
private static long longFactorial(long number) {
    if (number == 1) {
        return 1L;
    }
    Long result = longFactorials.get(number);
    if (result == null) {
        result = number * longFactorial(number - 1);
        longFactorials.put(number, result);
    }
    return result;
}

private static HashMap<Double, Double> doubleFactorials = new HashMap<>();
private static double doubleFactorial(double number) {
    if (number == 1) {
        return 1.;
    }
    Double result = doubleFactorials.get(number);
    if (result == null) {
        result = number * doubleFactorial(number - 1);
        doubleFactorials.put(number, result);
    }
    return result;
}

提前多多感谢。

2 个答案:

答案 0 :(得分:2)

您可以将乘法和递减函数传递给泛型方法:

private static Map<Number, Number> factorials = new HashMap<> ();

private static <T extends Number> T factorial(T n, BinaryOperator<T> multiply, UnaryOperator<T> decrement) {
  if (n.doubleValue() == 1) return n;
  T result = (T) factorials.get(n);
  if (result == null ){
    result = multiply.apply(n, factorial(decrement.apply(n), multiply, decrement));
    factorials.put(n, result);
  }
  return result;
}

然后你可以像这样改变原始方法:

public static int intFactorial(int number) {
  return factorial(number, (i, j) -> i * j, i -> i - 1);
}

警告:这种方法似乎会使Netbeans崩溃但使用javac编译好......

答案 1 :(得分:1)

如果您真的想要计算一个阶乘,那么doubleBigDouble之后就不需要factorial only applies to integer values了。由于这是真的,您可以将任何整数类型转换为BigInteger,并使用一个方法来获取任何Number返回BigInteger

这是一个测试类

public class Junk {
    public static void main(String[] args) {
        long val = 9;
        Junk j = new Junk();
        System.out.println(val + "! = " + j.factorial(val));
        BigInteger nine = new BigInteger("9");
        System.out.println(nine + "! = " + j.factorial(nine));
        short nine_short = 9;
        System.out.println(nine_short + "! = " + j.factorial(nine_short));
    }

    private HashMap<BigInteger, BigInteger> map = new HashMap<>();


    public BigInteger factorial(Number number){
        if(1 == number.intValue()){
            return BigInteger.ONE;
        }

        BigInteger bigInteger = new BigInteger(number.toString());
        BigInteger result = map.get(bigInteger);

        if(result == null){
            result = bigInteger.multiply(factorial(bigInteger.subtract(BigInteger.ONE)));
            map.put(bigInteger,result);
        }

        return result;
    }
}

输出

9! = 362880
9! = 362880
9! = 362880