web-dev-qa-db-fra.com

Gestion des flux null dans les flux Java avec facultatif

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

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

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

Utilisation de Stream.ofNullable en Java 9

List<UserDTOv2> users = Stream.ofNullable(studentsByCourseRoster.getUsers())
        .map(user -> {
            UserDTOv2 userDTO = new UserDTOv2();
            userDTO.populateUserDataFromUserDTO(user, groupedUsers);
            return userDTO;
        }).collect(Collectors.toList());
3
nullpointer

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. 

1
Aomine

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

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