2
votes

Comment retourner la liste entière si le filtre est faux

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 = ["1" ] 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 = ["1", "2", "3 "," 4 "," 5 "] . 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.


0 commentaires

5 Réponses :


2
votes

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)


1 commentaires

Ou simplement List filteredLst = split.get (! Split.get (true) .isEmpty ());



-1
votes

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));
    }


0 commentaires

1
votes

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;
}


1 commentaires

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 .



2
votes

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");


8 commentaires

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



0
votes

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


0 commentaires