C'è la possibilità di somma di ArrayList senza loop


88

C'è la possibilità di somma ArrayListsenza loop?

PHP fornisce sum(array)che darà la somma di array.

Il codice PHP è come

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

Volevo fare lo stesso in Java:

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

2
E se il ArrayListnon contiene qualcosa che è "sommabile"? ArrayList e un array non sono necessariamente la stessa cosa. Per quanto riguarda la somma dei numeri in un array, è un ciclo for molto semplice sugli elementi e il calcolo di una somma cumulativa.
posdef

La funzione PHP array_sumfa anche un ciclo internamente, lo nasconde semplicemente all'utente.
Paŭlo Ebermann

1
È una domanda ragionevole. Dopotutto, è quasi altrettanto banale scrivere un ciclo per trovare l'elemento più grande in un elenco, tuttavia java.util.Collections fornisce un metodo max ().
John Velonis

1
Domanda molto ragionevole, dopotutto, questo è il punto dei metodi, giusto? Riutilizzo :)
Ben Taliadoros

I loop sono bellissimi.
Alex78191

Risposte:


156

Una volta è uscito (marzo 2014) potrai utilizzare gli stream :

Se hai un List<Integer>

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

Se è un file int[]

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

5
maputilizza i loop in modo implicito
Nikos M.

8
È possibile utilizzare la ricorsione per non utilizzare un ciclo. : D (non farlo)
Caleb Fenton

23

Quindi scrivilo tu stesso:

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

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

     return sum;
}

1
O estendendo ArrayList con il metodo sum in modo da averlo integrato nel tuo ArrayList.
Bueller

3
Quando si esegue l'addizione effettiva, è semplicemente più bello usare un semplice file int. C'è poco valore nell'usare Integerqui le funzionalità di boxing automatico di java. Inoltre, stai creando e ricreando potenzialmente molti nuovi Integeroggetti ogni volta, poiché è un Immutabletipo.
Java Drinker

10

L'unica alternativa all'uso di un ciclo è usare la ricorsione.

Puoi definire un metodo come

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

Questo è molto inefficiente rispetto all'utilizzo di un semplice loop e può saltare in aria se si hanno molti elementi nell'elenco.

Un'alternativa che evita un overflow dello stack è usare.

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

Questo è altrettanto inefficiente, ma eviterà un overflow dello stack.


Il modo più breve per scrivere la stessa cosa è

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

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

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

stampe

sum(a) = 20

Nel codice si perde la chiamata a sum () nella prima definizione ricorsiva. La seconda definizione ricorsiva non impedisce che si verifichi un overflow dello stack, ma lo rende meno probabile.
Teudimundo

1
@Teudimundo True, anche se non lo impedisce, la dimensione massima di un List è Integer.MAX_VALUE e log2 è 31 che è la profondità massima. La maggior parte dei sistemi ha molte migliaia di chiamate come limite, ma se sei molto vicino a questo potrebbe comunque saltare.
Peter Lawrey

9

Scrivi una funzione util come

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

Quindi usa mi piace

int sum = ListUtil.sum(yourArrayList)

ma come posso farlo per un valore lungo in arraylist?
Ravi Parmar

5

per me il modo più chiaro è questo:

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

o

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

Utilizza anche loop interni, ma non è possibile senza loop.


2

Puoi utilizzare l'API delle collezioni comuni di 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;
        }
    }

Quindi utilizzare questa chiusura come mostrato di seguito:

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

1

Se conosci la funzione mappa, allora sai che una mappa può anche essere un ciclo ricorsivo o un ciclo ricorsivo. Ma ovviamente devi raggiungere ogni elemento per questo. quindi, non sono riuscito a risolvere Java 8, perché un po 'di mancata corrispondenza della sintassi ma volevo un molto breve quindi questo è quello che ho ottenuto.

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

Hai ragione. Ho detto che è un ciclo minimo invece di una mappa che può essere ricorsiva in coda.
sivi

"C'è la possibilità di somma di ArrayList senza loop"
alexander

0

Dato che un elenco può contenere qualsiasi tipo di oggetto, non esiste un metodo integrato che consenta di sommare tutti gli elementi. Potresti fare qualcosa del genere:

int sum = 0;

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

In alternativa puoi creare il tuo tipo di contenitore che eredita da ArrayList ma implementa anche un metodo chiamato sum () che implementa il codice sopra.


0

ArrayList è una raccolta di elementi (sotto forma di lista), le primitive vengono memorizzate come oggetto della classe wrapper ma allo stesso tempo posso memorizzare anche oggetti della classe String. SOMMA non avrà senso in questo. A proposito, perché hanno così paura di usare il ciclo for (migliorato o tramite iteratore) comunque?


0

Oppure passa a Groovy, ha una funzione sum () su una raccolta. [1,2,3,4,5,6] .somma ()

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

Funziona sulla stessa JVM delle classi Java.


8
Si. La funzione di somma è sicuramente un motivo per passare a un'altra lingua. : D
ruX

1
La domanda è contrassegnata Java, quindi questa non è tecnicamente una risposta valida.
Bengt

0

Questo collegamento mostra tre diversi modi per sommare in java, c'è un'opzione che non è nelle risposte precedenti usando Apache Commons Math ..

Esempio:

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

}

Vedere StatUtils api


0

Puoi usare la libreria GNU Trove :

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

0

Questo può essere fatto con reduce usando i riferimenti al metodo reduce(Integer::sum):

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

Oppure senza Optional:

Integer reduceSum = Arrays.asList(1, 3, 4, 6, 4)
        .stream()
        .reduce(0, Integer::sum);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.