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 Réponses :
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()); }
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!
Dans cette ligne mappez plutôt les identifiants de la department.getSectionId (). equals (sections.stream (). map (Section :: getId)
vous comparez un Long
à un Stream 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());
Je pense que la ligne .filter (department -> department.getSectionId ()! = Null)
n'est pas nécessaire, car Set.contains
renverra false code > si l'ensemble ne contient pas l'élément
null
.
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 .
C'est en effet vraiment sympa. Je vous remercie pour vos efforts!
Pouvez-vous partager vos modèles
DepartmentInfo
etSection
pour être précis.Dans cette ligne
department.getSectionId (). Equals (sections.stream (). Map (Secti on :: getId))
vous comparez unid
à unStream
, c'est pourquoi il est toujours faux. Cela n'a rien à voir avecLong
vsInteger
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;)