Есть ли возможность суммы ArrayList без цикла

87

Возможна ли сумма ArrayListбез зацикливания?

PHP предоставляет, sum(array)который даст сумму массива.

Код PHP похож на

$a = array(2, 4, 6, 8);
echo "sum(a) = " . array_sum($a) . "\n";

Я хотел сделать то же самое на Java:

List tt = new ArrayList();
tt.add(1);
tt.add(2);
tt.add(3);
Тапси
источник
2
Что делать, если в нем ArrayListнет чего-то «суммируемого»? ArrayList и массив - это не обязательно одно и то же. Что касается суммирования чисел в массиве, это очень простой цикл for по элементам и вычисление кумулятивной суммы.
posdef
Функция PHP array_sumтакже выполняет цикл внутри, она просто скрывает его от пользователя.
Паоло Эберманн
1
Разумный вопрос. В конце концов, почти так же тривиально написать цикл для поиска самого большого элемента в списке, но java.util.Collections предоставляет метод max ().
Джон Велонис
1
Очень разумный вопрос, ведь дело в методах, правда? Повторное использование :)
Бен Талиадорос
Петли красивые.
Alex78191

Ответы:

154

однажды отсутствует (март 2014 г.), вы сможете использовать потоки :

Если у тебя есть List<Integer>

int sum = list.stream().mapToInt(Integer::intValue).sum();

Если это int[]

int sum = IntStream.of(a).sum();
мсаяг
источник
5
mapнеявно использует циклы
Никос М.
6
Вы можете использовать рекурсию, чтобы не использовать цикл. : D (не делайте этого)
Калеб Фентон
23

Тогда напишите сами:

public int sum(List<Integer> list) {
     int sum = 0; 

     for (int i : list)
         sum = sum + i;

     return sum;
}
Эрхан Багдемир
источник
1
Или расширить ArrayList с помощью метода sum, чтобы он был встроен в ваш собственный ArrayList.
Bueller
3
При фактическом добавлении лучше использовать простой int. Здесь мало смысла в использовании Integerс функциями автоматической упаковки java. Кроме того, вы создаете и воссоздаете потенциально много новых Integerобъектов каждый раз, поскольку это Immutableтип.
Java Drinker
10

Единственная альтернатива использованию цикла - использовать рекурсию.

Вы можете определить такой метод, как

public static int sum(List<Integer> ints) {
   return ints.isEmpty() ? 0 : ints.get(0) + ints.subList(1, ints.length());
}

Это очень неэффективно по сравнению с использованием простого цикла и может взорваться, если у вас много элементов в списке.

Альтернативой, позволяющей избежать переполнения стека, является использование.

public static int sum(List<Integer> ints) {
    int len = ints.size();
    if (len == 0) return 0;
    if (len == 1) return ints.get(0);
    return sum(ints.subList(0, len/2)) + sum(ints.subList(len/2, len));
}

Это так же неэффективно, но позволит избежать переполнения стека.


Самый короткий способ написать то же самое -

int sum = 0, a[] = {2, 4, 6, 8};

for(int i: a) {
    sum += i;
}

System.out.println("sum(a) = " + sum);

печатает

sum(a) = 20
Питер Лоури
источник
В коде вы пропускаете вызов sum () в первом рекурсивном определении. Второе рекурсивное определение не предотвращает переполнение стека, оно снижает его вероятность.
Теудимундо
1
@Teudimundo True, хотя это не предотвращает этого, максимальный размер списка - Integer.MAX_VALUE, а log2 - 31, что является максимальной глубиной. У большинства систем есть много тысяч вызовов в качестве лимита, но если вы очень близко к нему, он все равно может взорваться.
Питер Лоури 03
9

Напишите служебную функцию вроде

public class ListUtil{

    public static int sum(List<Integer> list){
      if(list==null || list.size()<1)
        return 0;

      int sum = 0;
      for(Integer i: list)
        sum = sum+i;

      return sum;
    }
}

Затем используйте как

int sum = ListUtil.sum(yourArrayList)
Нишант
источник
но как я могу сделать это для длинного значения в arraylist?
Рави Пармар
5

для меня самый ясный способ таков:

doubleList.stream().reduce((a,b)->a+b).get();

или

doubleList.parallelStream().reduce((a,b)->a+b).get();

Также используются внутренние петли, но без петель это невозможно.

Ян Ябчан
источник
2

Вы можете использовать API общих коллекций apache.

class AggregateClosure implements org.apache.commons.collections.Closure {
        int total = 0;

        @Override
        public void execute(Object input) {
            if (input != null) {
                total += (Integer) input;
            }
        }

        public int getTotal() {
            return total;
        }
    }

Затем используйте это закрытие, как показано ниже:

public int aggregate(List<Integer> aList) {
        AggregateClosure closure = new AggregateClosure();
        org.apache.commons.collections.CollectionUtils.forAllDo(aList, closure);
        return closure.getTotal();
}
Хари Самала
источник
1

Если вы знаете о функции карты, то вы знаете, что карта также может быть рекурсивным циклом или рекурсивным циклом. Но, очевидно, для этого нужно дотянуться до каждого элемента. Итак, я не смог разработать Java 8 из-за некоторого несоответствия синтаксиса, но хотел очень короткого, так что это то, что я получил.

int sum = 0
for (Integer e : myList) sum += e;
сиви
источник
Ты прав. Я сказал, что это минимальный цикл, а не карта, которая может быть хвостовой рекурсивной.
sivi
«Возможна ли сумма ArrayList без зацикливания?»
Александр
0

Учитывая, что список может содержать любой тип объекта, нет встроенного метода, который позволяет суммировать все элементы. Вы можете сделать что-то вроде этого:

int sum = 0;

for( Integer i : ( ArrayList<Integer> )tt ) {
  sum += i;
}

В качестве альтернативы вы можете создать свой собственный тип контейнера, который наследуется от ArrayList, но также реализует метод под названием sum (), который реализует приведенный выше код.

Майк Кван
источник
0

ArrayList - это Коллекция элементов (в виде списка), примитивы хранятся как объект класса-оболочки, но в то же время я могу хранить и объекты класса String. СУММ в этом не имеет смысла. Кстати, почему все равно так боятся использовать цикл for (расширенный или через итератор)?

GauravJ
источник
0

Или переключитесь на Groovy, у него есть функция sum () для коллекции. [1,2,3,4,5,6] .sum ()

http://groovy.codehaus.org/JN1015-Collections

Работает на той же JVM, что и ваши классы Java.

dbrin
источник
8
Да уж. Функция Sum - определенно повод перейти на другой язык. : D
ruX
1
Вопрос отмечен тегами Java, поэтому технически это не верный ответ.
Bengt
0

Эта ссылка показывает три разных способа суммирования в java, есть один вариант, которого нет в предыдущих ответах с использованием Apache Commons Math ..

Пример:

public static void main(String args []){
    List<Double> NUMBERS_FOR_SUM = new ArrayList<Double>(){
         {
            add(5D);
            add(3.2D);
            add(7D);
         }
    };
    double[] arrayToSume = ArrayUtils.toPrimitive(NUMBERS_FOR_SUM
            .toArray(new Double[NUMBERS_FOR_SUM.size()]));    
    System.out.println(StatUtils.sum(arrayToSume));

}

См. API StatUtils.

начокк
источник
0

Вы можете использовать библиотеку GNU Trove :

TIntList tt = new TIntArrayList();
tt.add(1);
tt.add(2);
tt.add(3);
int sum = tt.sum();
Юрез
источник
0

Это можно сделать с помощью reduce, используя ссылки на методы reduce(Integer::sum):

Integer reduceSum = Arrays.asList(1, 3, 4, 6, 4)
        .stream()
        .reduce(Integer::sum)
        .get();

Или без Optional:

Integer reduceSum = Arrays.asList(1, 3, 4, 6, 4)
        .stream()
        .reduce(0, Integer::sum);
lczapski
источник