Чи існує можливість суми 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.