Java: общие методы и числа - PullRequest
16 голосов
/ 03 октября 2010

Я хочу создать общий метод, который составляет общую сумму List чисел.

Что я пытался это:

public static <T extends Number> T sumList(List<T> data)
{
    T total = 0;
    for (T elem : data)
    {
        total += elem;
    }
    return total;
}

Но проблема в том, что there is no += operator in T и что total can't be assigned to zero.

Как я могу это сделать?

Спасибо

Ответы [ 4 ]

18 голосов
/ 03 октября 2010

Есть способы, которыми вы можете взломать это вместе, но, честно говоря, дженерики - это просто не тот путь, по которому можно пойти сюда. Создайте метод для каждого конкретного примитивного типа оболочки и реализуйте их отдельно. Это будет слишком большая головная боль, чтобы сделать ее общей; арифметические операции не могут происходить в общем случае.

Вы тоже ничего не получите, сделав это общим. Это такой простой и постоянный код, что вы не беспокоитесь о дублировании кода, поскольку он не изменится. И люди не будут передавать свой собственный номер в ваш код; область типов, к которой он применяется, уже хорошо определена и конечна.

4 голосов
/ 03 октября 2010

Я сделал это недавно (основываясь на lambdaj коде) остерегайтесь, что все ваши элементы должны быть одного типа (вы не можете реально добавить Byte и BigDecimal)и может выдать CCE, если это не так и не будет обрабатывать пользовательские Number:

public class SumAggregator<T extends Number> {
    public T aggregate(Iterable<T> iterable) {
        T result = null;
        for (T item : iterable) {
            result = aggregate(result, item);
        }
        return result;
    }


    @SuppressWarnings("unchecked")
    protected T aggregate(T first, T second) {
        if (first == null) {
            return second;
        } else if (second == null) {
            return first;
        } else if (first instanceof BigDecimal) {
            return (T) aggregate((BigDecimal) first, (BigDecimal) second);
        } else if (second instanceof BigInteger) {
            return (T) aggregate((BigInteger) first, (BigInteger) second);
        } else if (first instanceof Byte) {
            return (T) aggregate((Byte) first, (Byte) second);
        } else if (first instanceof Double) {
            return (T) aggregate((Double) first, (Double) second);
        } else if (first instanceof Float) {
            return (T) aggregate((Float) first, (Float) second);
        } else if (first instanceof Integer) {
            return (T) aggregate((Integer) first, (Integer) second);
        } else if (first instanceof Long) {
            return (T) aggregate((Long) first, (Long) second);
        } else if (first instanceof Short) {
            return (T) aggregate((Short) first, (Short) second);
        } else {
            throw new UnsupportedOperationException("SumAggregator only supports official subclasses of Number");
        }
    }

    private BigDecimal aggregate(BigDecimal first, BigDecimal second) {
        return first.add(second);
    }

    private BigInteger aggregate(BigInteger first, BigInteger second) {
        return first.add(second);
    }

    private Byte aggregate(Byte first, Byte second) {
        return (byte) (first + second);
    }

    private Double aggregate(Double first, Double second) {
        return first + second;
    }

    private Float aggregate(Float first, Float second) {
        return first + second;
    }

    private Integer aggregate(Integer first, Integer second) {
        return first + second;
    }

    private Long aggregate(Long first, Long second) {
        return first + second;
    }

    private Short aggregate(Short first, Short second) {
        return (short) (first + second);
    }
}

Этот код выполняется на ideone с примерами .

0 голосов
/ 17 июня 2012

Посмотрите на следующий пример универсального метода суммирования списков переменных любого типа ... Я уверен, что это то, что вы просили ..

Марк Питерс также прав в своем ответе, но это также решение, к которому можно обратиться.

public class GenericSum {
@SuppressWarnings("unchecked")
public static <E> E sumArray(E[] inputArray) {
    Double result = 0.0;
    // Sum array elements
    for (E element : inputArray) {
        result = ((Number) result).doubleValue()
                + ((Number) element).doubleValue();
    }
    return ((E) result);
}

public static void main(String args[]) {
    // Create arrays of Integer, Double
    Integer[] intArray = { 1, 2, 3, 4, 5 };
    Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };

    System.out.println("Sum of doubles : " + sumArray(intArray));
    System.out.println("Sum of doubles : " + sumArray(doubleArray));
}

}
0 голосов
/ 15 января 2011

Вы можете использовать библиотеку, например Generic Java Math (ее часть чисел), которая предоставляет общие операции для подклассов Number. Он предоставляет способ работы с числами в общем, как в вашем примере, но с передачей объекта Arithmetics, который выполняет фактические вычисления. Смотрите пример на домашней странице.
Он должен использовать коробочные типы, поэтому, если вам нужна скорость, никакая общая реализация не может сделать это в Java, вы должны использовать примитивные типы.

...