Чи існує можливість суми 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також виконує цикл внутрішньо, вона просто приховує його від користувача.
Paŭlo Ebermann

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 () у першому рекурсивному визначенні. Друге рекурсивне визначення не запобігає переповненню стека, воно робить його менш імовірним.
Teudimundo

1
@Teudimundo Правда, хоча це не заважає, максимальний розмір Списку - це Integer.MAX_VALUE, а log2 - 31, що є максимальною глибиною. У більшості систем обмеження кількості тисяч дзвінків, але якщо ви дуже близькі до цього, це все одно може пробити.
Пітер Лорі

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 є колекцією елементів (у вигляді списку), примітивні зберігаються як об'єкт класу - оболонки , але в той же час я можу зберігати об'єкти класу Струнного а. SUM не матиме в цьому сенсу. До речі, чому так бояться використовувати цикл for (покращений або через ітератор) у будь-якому випадку?


0

Або перейдіть на Groovy, він має функцію sum () для колекції. [1,2,3,4,5,6] .sum ()

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

Працює на тій самій JVM, що і ваші класи Java.


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));

}

Див. StatUtils api


0

Ви можете використовувати бібліотеку GNU Trove :

TIntList tt = new TIntArrayList();
tt.add(1);
tt.add(2);
tt.add(3);
int sum = tt.sum();

0

Це можна зробити за допомогою зменшення за допомогою посилань на методи 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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.