4
votes

Conversion / comparaison de différents types numériques à l'intérieur de flux

Je rencontre encore un problème avec l'API Stream. La fonctionnalité que j'essaie de mettre en œuvre n'est pas la chose la plus difficile, mais j'ai des difficultés à filtrer car il existe des types incompatibles et je ne sais pas comment faire la comparaison correctement. L'idée est d'obtenir des informations sur les départements auxquels les sections données sont liées.

department.getSectionId () renvoie Long tandis que Section :: getId code> est un Integer (que je ne peux pas changer)

private List<DepartmentInfo> retrieveLinkedDepartments(final Collection<Section> sections) {
        return this.departmentDao
                .findAll()
                .stream()
                .filter(department -> department.getSectionId() != null)
                .filter(department -> department.getSectionId().equals(sections.stream().map(Section::getId)))                                           
                .map(this.departmentInfoMapper::map)
                .collect(Collectors.toList());
}

Bien sûr, le résultat du prédicat principal est toujours faux. Je sais que le code est horrible et que je ne définis pas correctement les conditions, mais j'espère que vous comprenez l'idée. Il est peut-être possible de fusionner ces collections ou de les comparer de manière intelligente.

Merci d'avance!


3 commentaires

Pouvez-vous partager vos modèles DepartmentInfo et Section pour être précis.


Dans cette ligne department.getSectionId (). Equals (sections.stream (). Map (Secti‌ on :: getId)) vous comparez un id à un Stream , c'est pourquoi il est toujours faux. Cela n'a rien à voir avec Long vs Integer dans ce cas précis.


@Hulk ouais, j'ai découvert ça dans un débogueur. Je voulais juste être aussi concis que possible en écrivant la question. Je ne savais tout simplement pas comment comparer;)


3 Réponses :


4
votes

Vous recherchez peut-être quelque chose comme:

Set<Long> sectionIds = sections.stream()
            .mapToLong(Section::getId)
            .boxed()
            .collect(Collectors.toSet());

Offcourse le résultat du prédicat principal est toujours faux

C'est parce que vous avez comparé Long généré en utilisant department.getSectionId () avec Stream généré en utilisant sections.stream (). map (Section :: getId) , la comparaison de ces deux types serait toujours inégale et donc le résultat false .

Modifier : comme indiqué par Holger dans les commentaires, le code de préparation de l ' Set peut être amélioré comme suit:

private List<DepartmentInfo> retrieveLinkedDepartments(final Collection<Section> sections) {
    Set<Long> sectionIds = sections.stream()
            .map(Section::getId)
            .map(Long::valueOf)
            .collect(Collectors.toSet()); // collect all the possible sectionIds
    return this.departmentDao
            .findAll()
            .stream()
            .filter(department -> department.getSectionId() != null)'
            // validate if the sectionIds include this department's section id or not
            .filter(department -> sectionIds.contains(department.getSectionId()))
            .map(this.departmentInfoMapper::map)
            .collect(Collectors.toList());
}


3 commentaires

Au lieu de .map (Section :: getId) .map (Long :: valueOf) vous pouvez utiliser .mapToLong (Section :: getId) .boxed () ou encore plus simple , .map (s -> (long) s.getId ()) . Mais en général, il est préférable d'utiliser un Set préparé au streaming sur les sections encore et encore…


@Holger Eh bien oui, préparer le Set me semble également préférable. Je voulais dire que l'autre approche était intéressante en raison de la façon dont elle réutilisait intelligemment le code de la question.


Merci beaucoup! C'est une belle alternative!



2
votes

Dans cette ligne department.getSectionId (). equals (sections.stream (). map (Section :: getId) vous comparez un Long à un Stream qui donnera toujours false.

mappez plutôt les identifiants de la Section à un Set , puis utilisez contient dans l'opération filter :

Set<Long> ids = sections.stream() // Stream<Section>
                        .map(Section::getId) //Stream<Integer>
                        .filter(Objects::nonNull) // remove potential null elements
                        .map(Integer::longValue) // Stream<Long>
                        .collect(Collectors.toSet()); //Set<Long>

return this.departmentDao
           .findAll()
           .stream()
           .filter(department -> department.getSectionId() != null)
           .filter(department -> ids.contains(department.getSectionId()))
           .map(this.departmentInfoMapper::map)
           .collect(Collectors.toList());


1 commentaires

Je pense que la ligne .filter (department -> department.getSectionId ()! = Null) n'est pas nécessaire, car Set.contains renverra false si l'ensemble ne contient pas l'élément null .



6
votes

Pour l'instant, vous comparez un Long et un Steam qui renverra toujours faux.

Vous pouvez inverser un peu votre logique et utiliser un mapToLong pour convertir les int en Long's:

private List<DepartmentInfo> retrieveLinkedDepartments(final Collection<Section> sections) {
    return this.departmentDao
               .findAll()
               .stream()
               .filter(department -> department.getSectionId() != null)
               .filter(department -> sections.stream()
                                 .mapToLong(Section::getId)                                     
                                 .anyMatch(department.getSectionId()::equals))                                           
               .map(this.departmentInfoMapper::map)
               .collect(Collectors.toList());
}

Cela convertira Section :: getId à un Stream , puis filtrez le Stream pour voir si l'un des department.getSectionId est égal à l'ID .


1 commentaires

C'est en effet vraiment sympa. Je vous remercie pour vos efforts!