Comment additionner une liste d'entiers avec des flux java?

Je veux additionner une liste d'entiers. Cela fonctionne comme suit, mais la syntaxe ne se sent pas bien. Le code pourrait-il être optimisé?

Map<String, Integer> integers;
integers.values().stream().mapToInt(i -> i).sum();
243
demandé sur Freek de Bruijn 2015-05-08 16:39:09

6 réponses

Cela fonctionnera, mais le i -> i fait un déballage automatique, c'est pourquoi il "se sent" étrange. L'un ou l'autre des éléments suivants fonctionnera et expliquera mieux ce que fait le compilateur sous le capot avec votre syntaxe originale:

integers.values().stream().mapToInt(i -> i.intValue()).sum();
integers.values().stream().mapToInt(Integer::intValue).sum();
339
répondu Necreaux 2015-05-08 13:50:02

Je suggère 2 autres options:

integers.values().stream().mapToInt(Integer::intValue).sum();
integers.values().stream().collect(Collectors.summingInt(Integer::intValue));

, La seconde utilise Collectors.summingInt() collectionneur, il y a aussi un summingLong() collector que vous utiliseriez avec mapToLong.


Et une troisième option: Java 8 introduit un très efficace LongAdder accumulateur conçu pour accélérer la synthèse dans les flux parallèles et les environnements multi-threads. Ici, voici un exemple d'utilisation:

LongAdder a = new LongAdder();
map.values().parallelStream().forEach(a::add);
sum = a.intValue();
118
répondu Alex Salauyou 2017-07-13 16:50:43

À partir des documents {[8]

Opérations de réduction Une opération de réduction (également appelée pli) prend une séquence d'éléments d'entrée et les combine en un seul résultat récapitulatif par application répétée d'une opération de combinaison, telle que trouver la somme ou le maximum d'un ensemble de nombres, ou accumuler des éléments dans une liste. Les classes de flux ont plusieurs formes d'opérations de réduction générales, appelées reduce () et collect (), ainsi que plusieurs formes de réduction spécialisées comme sum(), max(), ou count().

Bien sûr, de telles opérations peuvent être facilement implémentées sous forme de boucles séquentielles simples, comme dans:

int sum = 0;
for (int x : numbers) {
   sum += x;
}

Cependant, il y a de bonnes raisons de préférer une opération de réduction à une accumulation mutative telle que celle ci-dessus. Non seulement une réduction est "plus abstraite" - elle fonctionne sur le flux dans son ensemble plutôt que sur des éléments individuels-mais une opération de réduction correctement construite est intrinsèquement parallélisable, tant que la ou les fonctions utilisées pour processus les éléments sont associatifs et sans état. Par exemple, étant donné un flux de nombres pour lesquels nous voulons trouver la somme, nous pouvons écrire:

int sum = numbers.stream().reduce(0, (x,y) -> x+y);

Ou:

int sum = numbers.stream().reduce(0, Integer::sum);

Ces opérations de réduction peuvent fonctionner en toute sécurité en parallèle avec presque aucune modification:

int sum = numbers.parallelStream().reduce(0, Integer::sum);

Donc, pour une carte, vous utiliseriez:

integers.values().stream().mapToInt(i -> i).reduce(0, (x,y) -> x+y);

Ou:

integers.values().stream().reduce(0, Integer::sum);
63
répondu J Atkin 2016-02-02 20:38:39

Vous pouvez utiliser la méthode reduce:

long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, (x, y) -> x + y);

Ou

long sum = result.stream().map(e -> e.getCreditAmount()).reduce(0L, Integer::sum);
18
répondu Saeed Zarinfam 2017-12-25 11:33:37

Vous pouvez utiliser recueillir méthode pour ajouter une liste d'entiers.

List<Integer> list = Arrays.asList(2, 4, 5, 6);
int sum = list.stream().collect(Collectors.summingInt(Integer::intValue));
4
répondu Ashish Jha 2018-03-18 06:41:04

Vous pouvez utiliser reduce() pour additionner une liste d'entiers.

int sum = integers.values().stream().reduce(0, Integer::sum);
3
répondu Johnson Abraham 2018-08-26 00:18:20