L'équivalent de la Scala, à la foldLeft dans Java 8
Ce qui est l'équivalent de la Scala, à la grande foldLeft
dans Java 8?
J'ai été tenté de penser que c'était reduce
, mais de réduire doit retourner quelque chose de type identique à ce qu'il réduit sur.
Exemple:
import java.util.List;
public class Foo {
//this method works pretty well
public int sum(List<Integer> numbers) {
return numbers.stream()
.reduce(0, (acc, n) -> (acc + n));
}
//this method makes the file not compile
public String concatenate(List<Character> chars) {
return chars.stream()
.reduce(new StringBuilder(""), (acc, c) -> acc.append(c)).toString();
}
}
Le problème dans le code ci-dessus est le acc
umulator: new StringBuilder("")
Ainsi, quelqu'un pourrait-il m'indiquer le bon équivalent de la foldLeft
/correction de mon code?
- Pour info: le nom de La langue est "la Scala", pas "la SCALA". (Je crois qu'il est dans une langue différente, appelée "la SCALA", qui n'est probablement pas celui que tu veux dire.)
- Connexes stackoverflow.com/questions/30736587/...
- sauf si vous avez une source pour qu'il soit une langue différente avec le même nom mais avec une majuscule, je serais très surpris. Je pense que le capitalisés orthographe vient du vieux gestionnaires qui sont utilisés pour les langues étant capitalisés, à l'instar de BASE et FORTRAN 😀
- J'ai essayé de googler pour elle, mais c'est un peu dur, car googler "SCALA" renvoie également les résultats pour "Scala". Je crois, je l'ai vu dans le contexte de ce que nous aurions appelé aujourd'hui le "big data analyse" sur IBM de milieu de gamme systèmes, mais avant le "big data" (ou Scala) étaient une chose. Cependant, j'ai personnellement jamais travaillé sur IBM de milieu de gamme systèmes, de sorte que je ne me souviens pas les noms des outils associés, des cadres, des bibliothèques ou des langues, afin d'effectuer une meilleure google requête. Le fait que la Scala est utilisé dans le big data, et IBM est lourdement en poussant Scala n'est pas exactement de l'aide, soit.
Vous devez vous connecter pour publier un commentaire.
Mise à jour:
Ici est la première tentative pour obtenir votre code fixe:
Il utilise le suivant réduire la méthode:
Il peut sembler déroutant, mais si vous regardez la documentation javadoc il y a une belle explication qui peut vous aider à comprendre rapidement les détails. La réduction est équivalent au code suivant:
Pour une explication plus approfondie, veuillez vérifier cette source.
Cette utilisation n'est pas correcte car elle viole le contrat de réduire les qui indique que l'accumulateur doit être associatif, à la non-ingérence, d'apatride, de la fonction pour l'intégration d'un élément supplémentaire en raison. En d'autres termes, puisque l'identité est mutable, le résultat sera brisée en cas d'exécution parallèle.
Comme indiqué dans les commentaires ci-dessous une bonne option est d'utiliser la réduction comme suit:
Le fournisseur
StringBuilder::new
sera utilisé pour créer des contenants réutilisables qui seront ensuite combinés.reduce
de cette façon. Les fonctions sont pas autorisé à modifier leurs paramètres. L'utilisation correcte est.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
. Voir Mutable réduction.reduce
de cette façon constitue une violation du contrat et doit être considéré comme cassé, même si elle peut faire de la destinée chose dans certaines circonstances. Plus particulièrement, il va se casser à coup sûr lors de l'utilisation d'un courant parallèle.StringBuilder
. Il n'y a pas de problème avec la commande.Il n'y a pas d'équivalent de
foldLeft
dans Java 8 du Flux de l'API. Comme d'autres l'ont noté,reduce(identity, accumulator, combiner)
est proche, mais il n'est pas équivalent avecfoldLeft
, car il nécessite le type résultantB
à combiner avec lui-même et associatif (en d'autres termes, être monoïde-like), une propriété que chaque type a.Il y a aussi une demande d'amélioration pour cette: ajouter des Flux.foldLeft() d'exploitation du terminal
De voir pourquoi les réduire ne fonctionne pas, considérez le code suivant, où vous avez l'intention d'exécuter une série d'opérations arithmétiques en commençant par nombre:
Si vous avez essayé d'écrire
reduce(2, fun, combine)
, ce combiner la fonction pourriez-vous passer qui combine deux nombres? L'ajout de ces deux nombres ensemble n'a clairement pas le résoudre. Aussi, la valeur2
n'est clairement pas un identité élément.Noter qu'aucune opération qui nécessite une exécution séquentielle peut être exprimée en termes de
reduce
.foldLeft
est en fait plus générique quereduce
: vous pouvez mettre en œuvrereduce
avecfoldLeft
mais vous ne pouvez pas mettre en œuvrefoldLeft
avecreduce
.La méthode que vous cherchez est
java.util.Flux de données.réduire
, notamment la surcharge de trois paramètres, de l'identité, de l'accumulateur, et la fonction binaire. C'est le bon équivalent à la Scala defoldLeft
.Cependant, vous êtes pas autorisés à utiliser Java
reduce
de cette façon, et non de la Scala, à lafoldLeft
pour cette question. Utilisationcollecter
à la place.reduce
. Sinon, comment auriez-vous la phrase que?(a,b) -> new StringBuilder().append(a).append(b)
, ce serait une utilisation légale, mais pas très efficace, par rapport à lacollect
solution.reduce(identity, accumulator, combiner)
implique un associatif combiner la fonction, qui n'est pas une exigence defoldLeft
, par conséquent, tous lesfoldLeft
construire peut être réécrit pourreduce
. Prenez l'exemple suivant, où la soustraction et la division ne sont pas associative:val ops = List(('+', 1), ('*', 4), ('-', 2), ('/', 5)) val fun: (Int, (Char, Int)) => Int = { case (x, ('+', y)) => x + y case (x, ('-', y)) => x - y case (x, ('*', y)) => x * y case (x, ('/', y)) => x / y } ops.foldLeft(2)(fun) // ((2 + 1) * 4 - 2) / 5
Les autres sont corrects, il n'y a pas d'équivalent si. Voici une util proche-
votre cas à l'aide de la méthode ci-dessus pourrait ressembler-
Ou sans le lambda méthode ref sucre,