J'ai une liste d'objets disons car
. Je veux filtrer cette liste en fonction de certains paramètres à l'aide de Java 8. Mais si le paramètre est null
, il renvoie NullPointerException
. Comment filtrer les valeurs NULL?
Le code actuel est le suivant
requiredCars = cars.stream().filter(c -> c.getName().startsWith("M"));
Ceci jette NullPointerException
si getName()
renvoie null
.
Dans cet exemple particulier, je pense que @Tagir est correct à 100%, insérez-le dans un filtre et effectuez les deux vérifications. Je n'utiliserais pas Optional.ofNullable
les options sont en réalité destinées aux types de retour qui ne font pas de logique ... mais vraiment, ni ici ni là-bas.
Je voulais souligner que Java.util.Objects
a une méthode de Nice pour cela dans un cas large, vous pouvez donc faire ceci:
cars.stream()
.filter(Objects::nonNull)
Ce qui effacera vos objets nuls. Pour ceux qui ne sont pas familiers, c'est le raccourci pour ce qui suit:
cars.stream()
.filter(car -> Objects.nonNull(car))
Pour répondre partiellement à la question en question, renvoyez la liste des noms de voiture commençant par "M"
:
cars.stream()
.filter(car -> Objects.nonNull(car))
.map(car -> car.getName())
.filter(carName -> Objects.nonNull(carName))
.filter(carName -> carName.startsWith("M"))
.collect(Collectors.toList());
Une fois que vous vous êtes habitué aux lambdas de sténographie, vous pouvez également le faire:
cars.stream()
.filter(Objects::nonNull)
.map(Car::getName) // Assume the class name for car is Car
.filter(Objects::nonNull)
.filter(carName -> carName.startsWith("M"))
.collect(Collectors.toList());
Malheureusement, une fois que vous .map(Car::getName)
vous retournerez uniquement la liste des noms, pas les voitures. Donc, moins belle mais répond pleinement à la question:
cars.stream()
.filter(car -> Objects.nonNull(car))
.filter(car -> Objects.nonNull(car.getName()))
.filter(car -> car.getName().startsWith("M"))
.collect(Collectors.toList());
Vous avez juste besoin de filtrer les voitures qui ont un nom null
:
requiredCars = cars.stream()
.filter(c -> c.getName() != null)
.filter(c -> c.getName().startsWith("M"));
Les réponses proposées sont excellentes. Je voudrais juste suggérer une amélioration pour traiter le cas de liste nulle en utilisant Optional.ofNullable
, nouvelle fonctionnalité dans Java 8 :
List<String> carsFiltered = Optional.ofNullable(cars)
.orElseGet(Collections::emptyList)
.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
Donc, la réponse complète sera:
List<String> carsFiltered = Optional.ofNullable(cars)
.orElseGet(Collections::emptyList)
.stream()
.filter(Objects::nonNull) //filtering car object that are null
.map(Car::getName) //now it's a stream of Strings
.filter(Objects::nonNull) //filtering null in Strings
.filter(name -> name.startsWith("M"))
.collect(Collectors.toList()); //back to List of Strings
Vous pouvez le faire en une seule étape de filtrage:
requiredCars = cars.stream().filter(c -> c.getName() != null && c.getName().startsWith("M"));
Si vous ne souhaitez pas appeler plusieurs fois getName()
(par exemple, c'est un appel coûteux), vous pouvez procéder comme suit:
requiredCars = cars.stream().filter(c -> {
String name = c.getName();
return name != null && name.startsWith("M");
});
Ou de manière plus sophistiquée:
requiredCars = cars.stream().filter(c ->
Optional.ofNullable(c.getName()).filter(name -> name.startsWith("M")).isPresent());
tu peux utiliser ça
List<Car> requiredCars = cars.stream()
.filter (t-> t!= null && StringUtils.startsWith(t.getName(),"M"))
.collect(Collectors.toList());