J'ai une méthode qui prend 2 listes comme paramètres et comme vous pouvez le voir dans le corps de la méthode, je souhaite filtrer et renvoyer le résultat à l'appelant. Je voulais convertir ce code en Java 8 avec les expressions lambda, mais je ne pouvais pas le comprendre. J'ai fini par créer plus d'un flux pour cela et cela dépasse l'objectif de ce refactoring (IMHO). Ce que je voulais savoir, c’est que, de manière simple, je reformule tout cela en un seul flux?
public Set<CustomerTrack> getCustomerTracks(List<CusomerTrack> tracks, List<Customer> customers) {
Set<CustomerTrack> tracksToSave = new HashSet<>();
for (Customer customer : customers) {
if (customer.getTrack() == null) {
continue;
}
Long allowedTrackId = customer.getTrack().getId();
for (CustomerTrack track : tracks) {
if (Long.valueOf(track.getId()).equals(allowedTrackId)) {
tracksToSave.add(track);
}
}
}
return tracksToSave;
}
On dirait que c'est ce que vous recherchez:
customers.stream()
.filter(c -> c.getTrack() != null)
.map(c -> c.getTrack().getId())
.flatMap(id -> tracks.stream().filter(track -> Long.valueOf(track.getId()).equals(id)))
.collect(Collectors.toSet());
Notez simplement que pour chaque id
, vous parcourez la liste complète de tracks
; cela a la complexité O(n*m)
. C’est généralement considéré comme mauvais et vous pouvez l’améliorer.
Pour le rendre meilleur, vous créeriez d’abord une HashSet
d’id à partir de Customer
; Ayant cette HashSet
, vous pouvez maintenant appeler contains
avec les identifiants qui vous intéressent, puisque contains
a une complexité temporelle de O(1)
(elle s'appelle vraiment amorted complex of O(1)
). Alors maintenant, votre complexité devient O(n)
+ O(1)
, mais puisque O(1)
est une constante, c’est vraiment O(n)
- bien meilleur que ce que vous aviez auparavant. Dans du code:
Set<Long> set = customers.stream()
.filter(c -> c.getTrack() != null)
.map(c -> c.getTrack().getId())
.collect(Collectors.toSet());
Set<CusomerTrack> tracksToSave = tracks.stream()
.filter(track -> set.contains(track.getId())
.collect(Collectors.toSet()));
Tout d'abord, vous pouvez créer un ensemble d'identifiants autorisés:
Set<Long> collect = customers.stream()
.filter(customer -> customer.getTrack() != null)
.map(customer -> customer.getTrack().getId())
.collect(Collectors.toSet());
Ensuite, vous pouvez remplir votre collection de pistes
Set<CusomerTrack> tracksToSave = tracks.stream()
.filter(track -> collect.contains(Long.valueOf(track.getId())))
.collect(Collectors.toSet());
Une manière supplémentaire de favoriser l'utilisation de la méthode de référence:
Set<Track> tracks =
customers.stream()
.map(Customer::getTrack) // customer to track
.filter(Objects::nonNull) // keep non null track
.map(Track::getId) // track to trackId
.flatMap(trackId -> tracks.stream() // collect tracks matching with trackId
.filter(t-> Long.valueOf(t.getId()).equals(trackId))
)
.collect(toSet());
Tu pourrais essayer quelque chose comme ça
customers
.stream()
.map(Customer::getTrack)
.filter(Objects::nonNull)
.map(CustomerTrack::getId)
.flatMap(trackId -> tracks
.stream()
.filter(track -> Long.valueOf(track.getId()).equals(trackId)))
.collect(Collectors.toSet());
Vous devez d'abord filtrer les valeurs NULL puis les filtrer avec la liste de customerTrack.
J'espère que cette réponse vous aidera.
return customers.stream().map(cust-> cust.track).filter(track -> track != null).
collect(Collectors.toList())
.stream().filter(track-> customerTracks.stream()
.anyMatch(ele -> ele.getId() ==
track.getId())).collect(Collectors.toSet());
L'opérateur important ici est flatMap
Set<CustomerTrack> tracksToSave = customers.stream()
.map(Customer::getTrack)
.filter(track -> track != null)
.flatMap(track -> {
tracks.stream.filter(it -> Long.valueOf(it.getId()).equals(track.getId())))
.collect(Collectors.toSet());
Essaye celui-là
customers.stream()
.filter(customer -> customer.getTrack() != null)
.map(c -> c.getTrack().getId())
.forEach(allowedTrackId -> {
tracks.stream()
.filter(track -> Long.valueOf(track.getId()).equals(allowedTrackId))
.forEach(tracksToSave::add);
});