Quelle serait la meilleure façon de gérer null si nous avons le senario comme ci-dessous
//mocking for demonstraton
studentsByCourseRoster.setUsers(null);
studentsByCourseRoster.getUsers().stream().forEach(user -> {
final UserDTOv2 userDTO = new UserDTOv2();
userDTO.populateUserDataFromUserDTO(user, groupedUsers);
users.add(userDTO);
});
Si vous souhaitez conserver la structure d'instruction unique, vous pouvez utiliser Optional.ofNullable
et remplacer null
par une liste vide:
Optional.ofNullable(studentsByCourseRoster.getUsers())
.orElse(Collections.emptyList())
.forEach(user -> {
final UserDTOv2 userDTO = new UserDTOv2();
userDTO.populateUserDataFromUserDTO(user, groupedUsers);
users.add(userDTO);
});
Avec une légère modification de la réponse de Mureinik, j'utiliserais plutôt:
List<UserDTOv2> users = Optional.ofNullable(studentsByCourseRoster.getUsers())
.orElse(Collections.emptyList())
.stream()
.map(user -> {
UserDTOv2 userDTO = new UserDTOv2();
userDTO.populateUserDataFromUserDTO(user, groupedUsers);
return userDTO;
}).collect(Collectors.toList());
Stream.ofNullable
en Java 9List<UserDTOv2> users = Stream.ofNullable(studentsByCourseRoster.getUsers())
.map(user -> {
UserDTOv2 userDTO = new UserDTOv2();
userDTO.populateUserDataFromUserDTO(user, groupedUsers);
return userDTO;
}).collect(Collectors.toList());
Quelle serait la meilleure façon de traiter null si nous avions un type de scénario similaire au dessous de
La solution la plus simple à votre conception actuelle consiste à le faire avec une instruction if
.
Cela ne veut pas dire que c'est le meilleur moyen de "gérer" ce problème, mais plutôt le meilleur moyen de gérer ceci n'est jamais de permettre à la liste d'être dans un état nul en premier lieu, comme mentionné également dans les commentaires.
Si vous avez une liste vide comme valeur par défaut, cela vous évitera une quantité considérable de vérifications if
autour de votre base de code en fonction du nombre de fois que getUsers()
est utilisé et, plus important encore, vous n'avez pas à vous soucier de NullPointerExeception
car elles ne devraient jamais se produire.
Sur une autre note, chaque fois que vous semblez voir votre propre appel stream()
sur une collection puis immédiatement appeler forEach
, vous devez réaliser que c'est faux; 1) dans le sens où vous pourriez facilement appeler forEach
directement sur la liste, c'est-à-dire studentsByCourseRoster.getUsers().forEach(...)
2) les flux et les effets secondaires ne fonctionnent tout simplement pas bien ensemble.
Une autre façon d'écrire cela avec facultatif, en plus de corriger la réponse de @ Murenik. Pas besoin de créer une liste vide, nous pouvons passer des cas d'exécution non null uniquement avec:
Optional.ofNullable(nullableUsers)
.ifPresent(users -> users.forEach(user -> {
// work with user
}));
Nullable optional fonctionne également très bien avec les références null imbriquées, par exemple. nous avons une structure:
class User {
@Getter
Address address;
}
class Address {
@Getter
String street;
}
alors au lieu d'écrire
if (user.getAddress() != null && user.getAddress().getStreet() != null) {
// work with street
}
nous pouvons utiliser facultatif:
Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getStreet)
.ifPresent(street -> {
// work with street
});
Vous pouvez également filtrer les objets nuls par filtre (Objects :: nonNull):
studentsByCourseRoster.getUsers().stream().filter(Objects::nonNull).forEach(user -> {
final UserDTOv2 userDTO = new UserDTOv2();
userDTO.populateUserDataFromUserDTO(user, groupedUsers);
users.add(userDTO);
});