Existe possibilidade de soma de ArrayList sem loop


87

Existe possibilidade de soma ArrayListsem loop?

PHP fornece o sum(array)que dará a soma do array.

O código PHP é como

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

Eu queria fazer o mesmo em Java:

List tt = new ArrayList();
tt.add(1);
tt.add(2);
tt.add(3);

2
E se o ArrayListnão contiver algo que seja "somatório"? ArrayList e um array não são necessariamente a mesma coisa. Quanto à soma dos números em uma matriz, é um loop for muito simples sobre os elementos e calcular uma soma cumulativa.
posdef

A função PHP array_sumtambém faz um loop internamente, apenas o esconde do usuário.
Paŭlo Ebermann

1
É uma pergunta razoável. Afinal, é quase tão trivial escrever um loop para localizar o maior elemento em uma lista, embora java.util.Collections forneça um método max ().
John Velonis

1
Pergunta muito razoável, afinal, esse é o ponto dos métodos, certo? Reutilizar :)
Ben Taliadoros

Loops são lindos.
Alex78191

Respostas:


154

Uma vez foi lançado (março de 2014), você poderá usar streams :

Se você tem um List<Integer>

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

Se for um int[]

int sum = IntStream.of(a).sum();

5
mapusa loops implicitamente
Nikos M.

6
Você pode usar recursão para não usar um loop. : D (não faça isso)
Caleb Fenton

23

Então escreva você mesmo:

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

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

     return sum;
}

1
Ou estender ArrayList com o método sum para que você o tenha integrado em seu próprio ArrayList.
Bueller

3
Ao fazer a adição real, é melhor usar um simples int. Há pouco valor em usar Integeros recursos de auto-boxing do java aqui. Além disso, você está criando e recriando potencialmente muitos Integerobjetos novos a cada vez, uma vez que é um Immutabletipo.
Bebedor de Java de

10

A única alternativa para usar um loop é usar recursão.

Você pode definir um método como

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

Isso é muito ineficiente em comparação com o uso de um loop simples e pode explodir se você tiver muitos elementos na lista.

Uma alternativa que evita um estouro de pilha é usar.

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

Isso é igualmente ineficiente, mas evitará um estouro de pilha.


A maneira mais curta de escrever a mesma coisa é

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

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

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

estampas

sum(a) = 20

No código, você perde a chamada para sum () na primeira definição recursiva. A segunda definição recursiva não impede que ocorra estouro de pilha, ela o torna menos provável.
Teudimundo

1
@Teudimundo True, embora não o impeça, o tamanho máximo de uma lista é Integer.MAX_VALUE e o log2 é 31 que é a profundidade máxima. A maioria dos sistemas tem muitos milhares de chamadas como limite, mas se você estiver muito próximo disso, ainda pode explodir.
Peter Lawrey

9

Escreva uma função util como

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

Então use como

int sum = ListUtil.sum(yourArrayList)

mas como posso fazer isso por um longo valor em arraylist?
Ravi Parmar

5

para mim a maneira mais clara é esta:

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

ou

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

Ele também usa loops internos, mas não é possível sem loops.


2

Você pode usar a API apache commons-Collections.

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

Em seguida, use este fecho conforme mostrado abaixo:

public int aggregate(List<Integer> aList) {
        AggregateClosure closure = new AggregateClosure();
        org.apache.commons.collections.CollectionUtils.forAllDo(aList, closure);
        return closure.getTotal();
}

1

Se você conhece a função de mapa, sabe que um mapa também pode ser um loop recursivo ou um loop recursivo. Mas obviamente você tem que alcançar cada elemento para isso. então, eu não consegui descobrir o Java 8, porque alguma incompatibilidade de sintaxe, mas queria um muito curto, então foi isso que consegui.

int sum = 0
for (Integer e : myList) sum += e;

Você está certo. Eu disse que é um loop mínimo em vez de um mapa, que pode ser recursivo na cauda.
sivi

"Há possibilidade de soma de ArrayList sem loop"
alexander

0

Dado que uma lista pode conter qualquer tipo de objeto, não existe um método embutido que permite somar todos os elementos. Você poderia fazer algo assim:

int sum = 0;

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

Como alternativa, você pode criar seu próprio tipo de contêiner que herda de ArrayList, mas também implementa um método chamado sum () que implementa o código acima.


0

ArrayList é uma coleção de elementos (na forma de lista), primitivos são armazenados como objetos da classe wrapper, mas ao mesmo tempo eu também posso armazenar objetos da classe String. SUM não fará sentido nisso. BTW, por que tem tanto medo de usar loop (aprimorado ou por meio de iterador) de qualquer maneira?


0

Ou mude para Groovy, ele tem uma função sum () em uma coleção. [1,2,3,4,5,6] .sum ()

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

É executado na mesma JVM que suas classes java.


8
Sim. A função de soma é definitivamente um motivo para mudar para outro idioma. : D
ruX

1
A pergunta está marcada Java, portanto, não é tecnicamente uma resposta válida.
Bengt

0

Este link mostra três maneiras diferentes de somar em java, há uma opção que não está nas respostas anteriores usando o Apache Commons Math.

Exemplo:

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

}

Consulte StatUtils api


0

Você pode usar a biblioteca GNU Trove :

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

0

Isso pode ser feito com a redução usando referências de método reduce(Integer::sum):

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

Ou sem Optional:

Integer reduceSum = Arrays.asList(1, 3, 4, 6, 4)
        .stream()
        .reduce(0, Integer::sum);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.