2 votes

Comment utiliser les flux Java et reduce() pour obtenir la somme des calculs avec la clé et la valeur de la Map ?

Essayez d'être aussi bref que possible.

J'ai cette carte : Map<Neuron,Float> connexions. Elle contient un Neuron-Objekt comme Clé et le poids de la connexion comme valeur.

La classe Neuron possède une méthode "getOutput" pour obtenir la valeur de sortie du neurone.

Ce que je veux faire, c'est passer en revue chaque neurone de la carte, calculer neuron.getOutput * connections.get(neuron) et additionner le tout dans une seule variable.

Existe-t-il un moyen élégant de faire cela avec Java-Streams ? Peut-être avec reduce ? J'ai essayé mais je n'ai pas réussi à le faire fonctionner correctement.

inputConnections.keySet().stream().reduce(
            0f,
            (accumulatedFloat, inputNeuron) -> accumulatedFloat + inputConnections.get(inputNeuron),
            Float::sum);

Je suppose que le 0f fait que tout est multiplié par 0.

Ce code semble fonctionner, mais j'aimerais une solution plus élégante.

AtomicReference<Float> tmp = new AtomicReference<>(0f);
    inputConnections.keySet().forEach(inputNeuron -> {
        tmp.updateAndGet(v -> new Float((float) (v + inputNeuron.getOutput() * inputConnections.get(inputNeuron))));
    });

4voto

Pavel Points 574

Vous pouvez également réaliser la même chose avec map et sum

inputConnections.entrySet().stream().mapToDouble(entry -> entry.getKey().getOutput() * entry.getValue()).sum()

3voto

user7 Points 8280

Votre approche utilisant réduire le site est (presque) correct. Cela devrait ressembler au deuxième extrait de code où vous multipliez la valeur du neurone output avec la valeur de la carte ( inputConnections.get(..) )

inputConnections.entrySet()
        .stream()
        .reduce(0f,
                (result, entry) -> result + entry.getKey().getOutput() * entry.getValue(),
                Float::sum);

0voto

Roland J. Points 66

Vous pouvez également utiliser flux parallèles (attention : cela n'a de sens que pour les grands ensembles de données). Si vous avez besoin de statistiques supplémentaires aux sum le collecteur summarizingDouble est utile :

DoubleSummaryStatistics sumStat = connections.entrySet().parallelStream()
                .map(entry -> Double.valueOf(entry.getKey().getOutput() * entry.getValue()))
                .collect(Collectors.summarizingDouble(Double::doubleValue));
System.out.println(sumStat);

Exemple de sortie : DoubleSummaryStatistics{count=3, sum=18.000000, min=4.000000, average=6.000000, max=8.000000}

Voici une version plus courte (merci Rob pour votre commentaire) :

sumStat = connections.entrySet().parallelStream()
        .mapToDouble(entry -> entry.getKey().getOutput() * entry.getValue())
        .summaryStatistics();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X