J'ai cette liste
List<String> filteredLst = lstStr.stream() .filter(data-> "1".equalsIgnoreCase(data)) .collect(Collectors.toList()); filteredLst.forEach(data2 -> System.out.println(data2));
Lorsque je recherche la chaîne "1" , elle doit renvoyer un List
et si la chaîne de recherche ne figure pas dans la liste, par exemple "0" , elle doit renvoyer l'intégralité de la List
. Cela peut-il être réalisé en utilisant java stream? Veuillez montrer un exemple.
J'ai essayé ceci en utilisant le code ci-dessous, mais je pourrais obtenir la liste complète en recherchant par exemple "0"
List<String> lstStr = new ArrayList<>(); lstStr.add("1"); lstStr.add("2"); lstStr.add("3"); lstStr.add("4"); lstStr.add("5");
Merci d'avance.
5 Réponses :
Vous pouvez partitionner sur un prédicat et renvoyer la liste non vide:
Map<Boolean, List<String>> split = lstStr.stream() .collect(Collectors.partitioningBy("1"::equalsIgnoreCase)); List<String> filteredLst = split.get(Boolean.TRUE).isEmpty() ? split.get(Boolean.FALSE) : //can also use lstStr instead split.get(Boolean.TRUE);
Collectors.partitioningBy ("1" :: equals)
renverra un 2 -entry map, où true
sera la clé des entrées qui répondent à votre filtre, et false
la clé du reste.
filteredLst
doit contenir la valeur mappée à true
si ce n'est pas vide, ou la valeur de false
sinon (ce qui serait sûrement la même que la liste originale)
Ou simplement List
Vérifiez d'abord si votre liste contient cette valeur. Si oui, filtrez la liste ou bien simplement imprimer la liste précédente
if(!lstStr.contains("0")) { lstStr.forEach(data2 -> System.out.println(data2)); }else { List<String> filteredLst = lstStr.stream() .filter(data-> "1".equalsIgnoreCase(data)) .collect(Collectors.toList()); filteredLst.forEach(data2 -> System.out.println(data2)); }
Un utilitaire simple possible pour cela serait d'utiliser contient
:
List<String> findAndReturn(List<String> lstStr, String value) { List<String> filteredLst = lstStr.stream() .filter(data -> data.equalsIgnoreCase(value)) .collect(Collectors.toList()); return filteredLst.isEmpty() ? lstStr : filteredLst; }
et pour les doublons possibles dans la liste:
List<String> findAndReturnValue(List<String> lstStr, String value) { return lstStr.contains(value) ? lstStr.stream() .filter(a -> a.equalsIgnoreCase(value)) // condition as in question .collect(Collectors.toList()) : lstStr; }
Comme pour les autres réponses, gardez à l'esprit que List.contains
n'a pas la même sémantique que le test via equalsIgnoreCase
.
Si vous n'avez pas besoin de gérer les doublons, vous pouvez procéder comme suit:
static <T> List<T> getOneOrAll(List<T> list, Predicate<T> predicate) { List<T> filteredList = list.stream() .filter(predicate) .collect(toList()); return filteredList.isEmpty() ? list : filteredList; } ... List<String> result = getOneOrAll(lstStr, "1"::equals); // or List<String> resultIgnoringCase = getOneOrAll(lstStr, "1"::equalsIgnoreCase);
Sinon, vous pouvez passer un prédicat et filtrer les doublons:
static List<String> getOneOrAll(List<String> list, String element) { return list.stream() .filter(element::equalsIgnoreCase) .findFirst() .map(Collections::singletonList) .orElse(list); } ... List<String> result = getOneOrAll(lstStr, "1");
Gardez à l'esprit que List.contains
n'a pas la même sémantique que equalsIgnoreCase
.
@Holger Oui, exactement. C'est pourquoi la fonction accepte un Predicate
générique. Un jour, l'OP voudra peut-être réutiliser la même fonction avec des conditions différentes.
Votre deuxième solution le fait. Votre première sélection via le contrôle list.contains
.
@Holger Cela a du sens. Mise à jour de la première solution. La seule mise en garde est que Arrays.asList (...)
renvoie une liste immuable.
La liste renvoyée par Arrays.asList
n'est pas immuable. Il prend toujours en charge la méthode set
. Il ne prend tout simplement pas en charge le redimensionnement, c'est-à-dire que add
et remove
ne fonctionnent pas. Mais comme il n'y a pas de spécification sur la mutabilité, je dirais que immuable serait bien, en particulier lorsque le résultat peut ou non être la liste d'origine, ce qui exclut la logique d'application sensible basée sur la mutabilité attendue. Par conséquent, vous pouvez également utiliser .map (Collections :: singletonList)
, qui renvoie une liste véritablement immuable (et plus efficace).
@ETO List :: of
serait vraiment immuable
@Eugene n'est-ce pas une fonctionnalité de Java9
?
@ETO ça l'est, oui
Vous pouvez utiliser Collector personnalisé à cette fin.
li.stream().filter(d->"0".equalsIgnoreCase(d)).collect( Collector.of( ArrayList::new, ArrayList::add, (a, b) -> { a.addAll(b); return a; }, a -> a.isEmpty() ? li : a ) );
Recherchez la documentation Collector: https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.html