Y a-t-il une possibilité de somme de ArrayList sans boucle

87

Y a-t-il possibilité de somme de ArrayListsans boucle?

PHP fournit sum(array)ce qui donnera la somme du tableau.

Le code PHP est comme

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

Je voulais faire la même chose en Java:

List tt = new ArrayList();
tt.add(1);
tt.add(2);
tt.add(3);
Tapsi
la source
2
Que faire si le ArrayListne contient pas quelque chose de "sommable"? ArrayList et un tableau ne sont pas nécessairement la même chose. En ce qui concerne la somme des nombres dans un tableau, c'est une boucle for très simple sur les éléments et le calcul d'une somme cumulative.
posdef
La fonction PHP fait array_sumégalement une boucle en interne, elle la masque simplement à l'utilisateur.
Paŭlo Ebermann
1
C'est une question raisonnable. Après tout, il est presque aussi simple d'écrire une boucle pour trouver le plus grand élément d'une liste, mais java.util.Collections fournit une méthode max ().
John Velonis
1
Question très raisonnable, après tout, c'est le but des méthodes, non? Reuse :)
Ben Taliadoros
Les boucles sont magnifiques.
Alex78191

Réponses:

154

Une fois que est sorti (mars 2014), vous pourrez utiliser les flux :

Si tu as un List<Integer>

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

Si c'est un int[]

int sum = IntStream.of(a).sum();
msayag
la source
5
maputilise des boucles implicitement
Nikos M.
6
Vous pouvez utiliser la récursivité pour ne pas utiliser de boucle. : D (ne faites pas ça)
Caleb Fenton
23

Alors écrivez-le vous-même:

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

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

     return sum;
}
Erhan Bagdemir
la source
1
Ou étendre ArrayList avec la méthode sum afin de l'avoir intégré à votre propre ArrayList.
Bueller
3
Lors de l'ajout proprement dit, il est juste plus agréable d'utiliser un simple int. Il y a peu de valeur à utiliser Integeravec les fonctionnalités d'auto-boxing de Java ici. En outre, vous créez et recréez potentiellement de nombreux nouveaux Integerobjets à chaque fois, car il s'agit d'un Immutabletype.
Java Drinker
10

La seule alternative à l'utilisation d'une boucle est d'utiliser la récursivité.

Vous pouvez définir une méthode comme

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

Ceci est très inefficace par rapport à l'utilisation d'une boucle simple et peut exploser si vous avez de nombreux éléments dans la liste.

Une alternative qui évite un débordement de pile est d'utiliser.

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

C'est tout aussi inefficace, mais cela évitera un débordement de pile.


Le moyen le plus court d'écrire la même chose est

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

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

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

impressions

sum(a) = 20
Peter Lawrey
la source
Dans le code, vous manquez l'appel à sum () dans la première définition récursive. La deuxième définition récursive n'empêche pas le débordement de pile, elle le rend moins probable.
Teudimundo
1
@Teudimundo True, bien que cela ne l'empêche pas, la taille maximale d'une liste est Integer.MAX_VALUE et le log2 est 31 qui est la profondeur maximale. La plupart des systèmes ont plusieurs milliers d'appels comme limite, mais si vous êtes très proche de cela, cela pourrait encore exploser.
Peter Lawrey
9

Ecrire une fonction util comme

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

Ensuite, utilisez comme

int sum = ListUtil.sum(yourArrayList)
Nishant
la source
mais comment puis-je le faire pour une valeur longue dans arraylist?
Ravi Parmar
5

pour moi, le moyen le plus clair est celui-ci:

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

ou

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

Il utilise également des boucles internes, mais ce n'est pas possible sans boucles.

Ján Яabčan
la source
2

Vous pouvez utiliser l'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;
        }
    }

Ensuite, utilisez cette fermeture comme indiqué ci-dessous:

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

Si vous connaissez la fonction de carte, vous savez qu'une carte peut également être une boucle récursive ou une boucle récursive. Mais il faut évidemment atteindre chaque élément pour cela. donc, je ne pouvais pas travailler sur le Java 8, car une certaine incohérence de syntaxe, mais je voulais un très court donc c'est ce que j'ai obtenu.

int sum = 0
for (Integer e : myList) sum += e;
sivi
la source
Tu as raison. J'ai dit que c'est une boucle minimale au lieu d'une carte qui peut être récursive en queue.
sivi
"Y a-t-il possibilité de somme de ArrayList sans boucle"
alexander
0

Étant donné qu'une liste peut contenir n'importe quel type d'objet, il n'y a pas de méthode intégrée qui vous permet de faire la somme de tous les éléments. Vous pouvez faire quelque chose comme ceci:

int sum = 0;

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

Vous pouvez également créer votre propre type de conteneur qui hérite de ArrayList mais implémente également une méthode appelée sum () qui implémente le code ci-dessus.

Mike Kwan
la source
0

ArrayList est une collection d'éléments (sous forme de liste), les primitives sont stockées en tant qu'objet de classe wrapper mais en même temps je peux également stocker des objets de classe String. SUM n'aura aucun sens à cet égard. BTW pourquoi avez-vous si peur d'utiliser la boucle for (améliorée ou via l'itérateur) de toute façon?

GauravJ
la source
0

Ou passez à Groovy, il a une fonction sum () sur une collection. [1,2,3,4,5,6] .sum ()

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

S'exécute sur la même JVM que vos classes java.

dbrin
la source
8
Ouais. La fonction Sum est certainement une raison pour passer à une autre langue. : D
ruX
1
La question est étiquetée Java, donc ce n'est techniquement pas une réponse valide.
Bengt
0

Ce lien montre trois façons différentes de faire la somme en java, il existe une option qui ne figure pas dans les réponses précédentes en utilisant Apache Commons Math.

Exemple:

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

}

Voir StatUtils api

nachokk
la source
0

Vous pouvez utiliser la bibliothèque GNU Trove :

TIntList tt = new TIntArrayList();
tt.add(1);
tt.add(2);
tt.add(3);
int sum = tt.sum();
yurez
la source
0

Cela peut être fait avec réduire en utilisant des références de méthode reduce(Integer::sum):

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

Ou sans Optional:

Integer reduceSum = Arrays.asList(1, 3, 4, 6, 4)
        .stream()
        .reduce(0, Integer::sum);
lczapski
la source