Java 8 lambda: convertir Collection de Carte de l'élément, l'itération de la position
Comment convertir une collection de comme ["a", "b", "c"] pour une carte comme {"a": 0, "b":1, "c":2} avec les valeurs de l'ordre de l'itération.
Est-il un liner avec des ruisseaux et des collectionneurs dans le JDK8?
Vieille façon, c'est comme cela:
Collection<String> col = apiCall();
Map<String, Integer> map = new HashMap<>();
int pos = 0;
for (String s : collection) {
map.put(s, pos++);
}
Notez que votre code va créer la carte
Vous pouvez être intéressé par stackoverflow.com/questions/17640754/...
merci, mis à jour à la question
{"a": 0, "b": 1, "c": 2}
, et les réponses ont suivi.Vous pouvez être intéressé par stackoverflow.com/questions/17640754/...
merci, mis à jour à la question
OriginalL'auteur danial | 2014-07-30
Vous devez vous connecter pour publier un commentaire.
Vous n'avez pas besoin d'un courant parallèle, vous pouvez utiliser la longueur de la carte, comme un index de compteur:
map.size()
indexation était cool.. 😉C'est une mauvaise solution, j'ai peur: ce n'est pas thread-safe, puisque les différents éléments peuvent être traitées par différents threads, même sur un flux séquentiel. Aussi (moins important) forEach n'est pas garanti pour maintenir l'ordre.
Nick naftalin: “séquentielle” est le face de “parallèle”. Peut-être que tu voulait dire “ordonné” qui peut toujours être parallèle.
Désolé, j'ai confondu ce fil en supprimant le commentaire que vous avez répondu, parce que je voulais la revoir. Pour tous ceux qui lisent ceci, ce que j'ai dit a été: "Non, je voulais dire ce que j'ai dit: "même sur un flux séquentiel". La documentation de java.util.ruisseau dit (à la rubrique "effets indésirables"): "Même quand un pipeline est contraint de produire un résultat qui est conforme à la rencontre de commande du flux source, aucune garantie n'est faite quant à ... ce thread n'importe quel comportement de paramètre est exécutée pour un élément donné."
Le problème avec le commentaire que j'ai supprimé, c'est que c'est vrai, mais inapplicable; l'expression que j'ai fait allusion à des documents le comportement des intermédiaires en opérations. La documentation que j'nécessaire ici, c'est pour
forEach
: "Pour tout élément donné, l'action peut être exécutée à n'importe quel moment et dans quel thread de la bibliothèque choisit. Si l'action accède à un état partagé, il est responsable de fournir la synchronisation requise." Donc cette solution n'est pas thread-safe. (forEachOrdered
ne souffre pas du même problème, de sorte que votre solution ci-dessous).OriginalL'auteur maba
Voici une approche:
Pas nécessairement un one-liner ou plus courte que la simple boucle, mais il fonctionne à l'aide d'un courant parallèle si vous modifiez
toMap
àtoConcurrentMap
.Noter également, cela suppose que vous avez un accès aléatoire de la liste, pas une
Collection
. Si vous avez unCollection
que vous pouvez faire aucune hypothèse sur, il n'ya pas beaucoup que vous pouvez faire d'autre que de parcourir de façon séquentielle et incrémenter un compteur.Mise à JOUR
L'OP a précisé que l'entrée est un
Collection
et pas unList
de sorte que le ci-dessus ne s'applique pas. Il semble que nous pouvons supposer que très peu de choses sur l'entréeCollection
. L'OP a précisé itération de l'ordre. Avec un séquentiel d'itérateur, les éléments seront dans certains ordonnance, mais aucune garantie ne peut être fait à ce sujet. Il peut changer d'exécuter pour exécuter, ou même d'une itération à l'autre (bien que ce serait inhabituel dans la pratique, à moins que la collection sous-jacente est modifié).Si l'exact itération doit être préservée, je ne crois pas qu'il y a un moyen de le préserver dans le résultat
Map
sans une itération à l'entréeCollection
de manière séquentielle.Si, toutefois, l'exacte itération de l'ordre n'est pas important, et la condition est que la sortie
Map
ont des valeurs uniques pour chaque élément d'entrée, alors il serait possible de faire quelque chose comme ceci en parallèle:C'est maintenant loin à partir d'un seul-liner. Il n'est également pas clair pour moi, combien il est utile. 🙂 Mais il ne démontrent qu'il est possible de faire quelque chose comme ceci en parallèle. Notez que nous avons eu pour synchroniser l'accès à la collection d'entrée de l'itérateur puisqu'il sera appelé à partir de plusieurs threads. Notez également que c'est une utilisation inhabituelle de l'itérateur, puisque nous n'avons jamais appel
hasNext
et nous supposons qu'il est possible d'appeler desnext
exactement le nombre de fois retourné par l'entrée de la collectionsize()
.Désolé, j'avais supposé un
List
. Merci pour la clarification. J'ai mis à jour la réponse à ne traiter qu'avec desCollection
. Vous pourrait ou ne pourrait pas trouver utile. 🙂i -> i
pourrait être remplacé parFunction.identity()
OriginalL'auteur Stuart Marks
Basé sur maba réponse la solution générale est:
De la la documentation de
void forEachOrdered(Consumer<? super T>)
:L'aspect important qu'il conserve l'ordre si il y en a un, par exemple, si le
Collection
est unSortedSet
ou unList
. Un tel flux est appelé un commandé flux (à ne pas confondre avec triés stream). Il pourrait invoquer la consommation de la méthode par des threads différents, mais toujours en s'assurant de la “un à un” fil et sécurité garantie.Bien sûr, il ne bénéficiera pas de l'exécution en parallèle si le flux est parallèle.
Pour être complet, voici la solution qui fonctionne même sur les flux parallèles en utilisant le traitement parallèle, si elles sont encore commandé:
OriginalL'auteur Holger
Si vous n'avez pas l'esprit à l'aide de la 3e partie des bibliothèques, mon cyclope-réagir lib a des extensions pour tous les JDK Collection types, avec un grand nombre de puissants operations attachés, de sorte que vous pourriez mettre en œuvre la présente comme suit :-
cyclope-réagir Collection extensions sont impatients, donc, vous obtiendrez de meilleures performances avec nos Flux extension, ReactiveSeq (qui s'étend à jOOλ du Seq, qui à son tour est une extension du JDK de java.util.flux de données.Cours d'eau, il met également en œuvre le réactif-api de flux).
OriginalL'auteur John McClean
Vous pouvez utiliser AtomicInteger comme indice de flux:
OriginalL'auteur K. Gol
Essayer
Je n'ai pas compris la question?
Un
Stream
ne semble pas être en cause ici.Les flux ne sont pas tenus de faire exécuter sur un seul thread. Par conséquent l'utilisation de
forEach
sur un cours d'eau peut résulter en parallèle de l'exécution de l'expression lambda.La même chose vaut pour
Iterator.forEach
, tel que précisé par cette phrase de la javadoc: "à Moins d'indication contraire par la mise en œuvre de la classe, les actions sont exécutées dans l'ordre d'itération". Cette phrase vous dit que l'ordre d'exécution ne peut pas être la même que dans l'itérateur. Et la question n'est pas de dire quel genre de collection est utilisée.OriginalL'auteur Syam S