Java 8 stream: remplacer l'élément en streaming collection
Je suis un peu nouveau pour Java 8, et je suis refactoring certains anciens de code avec (ce qui semble être un bon cas d'utilisation) d'un flux de l'opération. Le vieux code "fonctionne", mais à mes yeux elle a l'air vraiment inefficace.
La version courte de ma question est que je suis en train de trouver un seul élément d'une Liste et de le remplacer par une version mise à jour de ce même élément (la clé est la même, mais les propriétés ont des valeurs différentes à chaque fois que le code est appelé).
try
{
List<Object> items = lookup(itemCache.getKey());
for (int i = 0; i < items.size(); i++)
{
Object originalObject = items.get(i);
if (originalObject.getPropValue() == newObject.getPropValue())
{
List<Object> newItems = new ArrayList<>(items);
newItems.set(i, newObject);
putIntoCache(newObject.getKey(), newItems);
break;
}
}
}
catch (Exception ex) { /*exception handling*/ }
Fondée sur ce que j'ai lu sur les ruisseaux jusqu'à présent, il semble que j'ai besoin d'utiliser un .map()
ou .filter()
pour isoler l'élément que je veux à identifier, mais qui semble aussi que des opérations survenues après la filter
ou map
dans le cours d'eau serait d'exploitation sur la Liste non complète ou sur une Liste où chaque élément est affecté par la .map()
.
Cela semble simple, mais j'ai du mal à envelopper ma tête autour de lui. Parce que la première recherche est un List
lui-même, je pensais le flux pourrait remplacer tout cela. Le ArrayList<>()
apparaît dans le code d'origine, mais l'ordre des éléments n'a pas d'importance tant que je suis en mesure de remplacer cet article par sa clé.
Si vous choisissez de vous aider, je vous remercie.
- Les flux ne sont pas appropriées pour les mutations de la source de données.
- Hors sujet, mais si votre cache met en œuvre
Map
, vous devriez regarder dansMap.computeIfPresent(UnaryOperator<T>)
au lieu de lire leList
et de l'écrire dans le cache. LecomputeIfAbsent
est thread-safe dans un ConcurrentHashMap, à la différence de la lecture-modification-écriture approche adoptée dans ces réponses.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez tout simplement faire:
items.stream().map(o -> o.getPropValue() == newObject.getPropValue()? newObject: o).collect(toList())
newItems
est une mutable copie des données dans le cache, vous pouvez utilisernewItems.replaceAll()
au lieu de laStream
.La fonction que vous souhaitez appliquer est "remplacer la première élément qui correspond à la prop valeur". Le première partie (et instruction break) sont non triviales (comme vous comptez sur toutes les entrées traitées avant que). En d'autres termes, cela implique que votre fonction dépend d'un état supplémentaire, de sorte que le domaine peut être exprimée comme
boolean * String
, où booléen indique si le remplacement a été fait. Vous pouvez voir qu'il commence à devenir laid.Si vous êtes d'accord avec le remplacement de tous des valeurs correspondantes, puis Jean Logeart la réponse semble d'accord.
Les flux sont en fait pas particulièrement bon pour cet extrait de code, car elle a un début
break
et, simultanément, fonctionne à la fois avec des indices et des éléments.Vous pouvez construire une mention équivalente comme ceci:
Est-ce vraiment mieux? À mon avis, pas particulièrement. Nous ne sommes pas vraiment à l'aide de l'un quelconque des flux de fonctionnalités, comme le remplacement de flux de contrôle de la syntaxe de l'API.
Si le comportement exact est moins important, alors il y a peut-être mieux d'exemples, comme Jean de la réponse.