Java 8 Flux de rechercher un élément dans la liste
J'ai la classe suivante:
public class Item {
int id;
String name;
//few other fields, contructor, getters and setters
}
J'ai une liste d'Éléments. Je veux parcourir la liste pour trouver l'exemple qui a un id particulier. Je suis en train de le faire dans les ruisseaux.
public void foobar() {
List<Item> items = getItemList();
List<Integer> ids = getIdsToLookup();
int id, i = ids.size() - 1;
while (i >= 0) {
id = ids.get(i);
Optional<Item> item = items
.stream()
.filter(a -> a.getId() == id)
.findFirst();
//do stuff
i--;
}
}
Est-ce la meilleure façon d'itérer sur la liste et obtenir l'élément que j'ai besoin? Aussi, j'obtiens une erreur sur le filtre de ligne pour l'id qui dit que les variables utilisées dans les expressions lambda doit être définitive ou efficacement final. Peut-être que je peux définir l'id à l'intérieur de la boucle while, qui devrait se débarrasser de l'exception. Merci.
Vous utilisez la même variable i pour l'index dans la liste, et pour l'élément courant dans le lambda. Choisir un nom différent. Ce code est bien, mais tout à fait inefficace. Si vous avez de multiples identifiants et ont besoin de trouver l'élément correspondant pour tous, à commencer par la création d'une HashMap<Integer, Item>, et ensuite utiliser la table de hachage.
Je suis en utilisant une autre variable dans mon code, j'ai essayé de simplifier le code ici. Je vais le changer.
Déclarer la variable
Ouais, c'est ce que je pensais. Merci pour la suggestion.
De même pour la boucle BTW, utilisez
Je suis en utilisant une autre variable dans mon code, j'ai essayé de simplifier le code ici. Je vais le changer.
Déclarer la variable
id
à l'intérieur la boucle, et il sera effectivement final. En étant à l'extérieur, vous réinitialiser à chaque itération, et c'est donc pas définitive. Déclarer des variables dans la portée plus petite possible est une meilleure pratique en général.Ouais, c'est ce que je pensais. Merci pour la suggestion.
De même pour la boucle BTW, utilisez
for (int i = 0; i < ids.size(); i++)
, ou encore mieux et plus simple: for (Integer id : ids)
OriginalL'auteur Gengis Khan | 2016-03-10
Vous devez vous connecter pour publier un commentaire.
Si vous avez beaucoup d'id pour la recherche, il est recommandé d'utiliser une solution qui ne en un seul passage, plutôt que de faire une recherche linéaire pour chaque id:
La première déclaration suffit de créer une carte de la liste id, la cartographie de chaque id de recherche à un vide
Optional
.La deuxième instruction effectue une itération sur les éléments à l'aide de
forEach
et pour chaque élément, il vérifie si il y a une cartographie à partir de son id à un videOptional
et de le remplacer avec unOptional
de l'encapsulation de l'article, si il ya une telle cartographie, en une seule opération,computeIfPresent
.La dernière
for
boucle itère vers l'arrière sur leids
liste, comme vous le souhaitiez à les traiter dans l'ordre et effectuer l'action s'il y a un non-videOptional
. Depuis que la carte a été initialisé avec tous les codes trouvés dans la liste,get
ne reviendra jamaisnull
, il sera de retour un videOptional
, si l'id n'a pas été trouvé dans laitems
liste.De cette façon, en supposant que le
Map
’s de recherche aO(1)
temps de la complexité, ce qui est le cas typique des implémentations, le temps net de la complexité changé deO(m×n)
àO(m+n)
...Khan: il fait exactement ce que vous voulez. Le
for
est une itération de la boucle vers l'arrière sur leids
liste comme vous le souhaitiez.OriginalL'auteur Holger
Vous pouvez essayer d'utiliser quelque chose comme ceci:
Facultatif montre ici que votre filtre méthode peut retourner un vide stream, donc si vous appelez la méthode findFirst il peut trouver un ou zéro éléments.
findFirst()
avecfindAny()
permettrait d'améliorer les performances ici. stackoverflow.com/questions/35359112/...OriginalL'auteur ByeBye
Si vous voulez coller avec des ruisseaux et itérer en arrière, vous pourriez faire de cette façon:
Ce code n'est le même que le vôtre.
Il parcourt à rebours, en commençant avec une graine:
ids.size() - 1
. La première de flux deint
s est limité dans sa taille aveclimit()
, de sorte qu'il n'y a pas négatifint
s et le flux a la même taille que la liste desids
. Puis, unmap()
opération convertit l'indice de la réelleid
qui est à la nième position à laids
liste (ce qui est fait par le biais de l'invocation d'ids.get(i)
). Enfin, l'élément est recherché dans leitems
liste de la même façon que dans votre code.O(n)
de la complexité de toute façon...Je veux dire plus de
ids
listeMaintenant, je vois ce que tu veux dire, d'éditer pour supprimer la note. Merci!
OriginalL'auteur Federico Peralta Schaffner
Vous voulez trouver au plus un élément pour chaque id et faire quelque chose avec l'élément trouvé, non? Un peu plus de l'amélioration de la performance:
OriginalL'auteur user_3380739