2
votes

Comment filtrer les données d'une liste en fonction de plusieurs paramètres en Java?

J'ai une liste de GroupOffices

 public GroupOfficeDto saveGroupOffice(GroupOfficeDto groupOfficeDto) {     
            List<GroupOffice> officesOfTheGroup = //some list from db..
            for (GroupOffice go : officesOfTheGroup) {
                if ((!go.getId().equals(groupOfficeDto.getId())) && go.getLabel().equals(groupOfficeDto.getLabel())) {
                    return groupOfficeDto;
                }
        return null:
}

Je veux rechercher si l'id n'est pas égal à groupOffice.getId (Long value) mais le libellé est groupOffice.getLabel (String) et attribuez-le à un booléen. Le code ci-dessous fonctionne bien, mais y a-t-il une meilleure approche au lieu de parcourir tous les éléments avec la boucle for?

List<GroupOffice> officesOfTheGroup;

Ou comment puis-je utiliser stream? Si c'est le cas, est-ce que l'utilisation de stream est une meilleure approche?

Remarque: J'utilise Java8


3 commentaires

Je veux rechercher si un identifiant vaut 5 mais le libellé n'est pas Londres et l'assigner à un booléen votre code fait le contraire.


Je suis confus. Le code que vous présentez semble effectuer un test opposé à celui que vous décrivez.


merci pour les commentaires, j'ai édité la question. le code est correct


3 Réponses :


1
votes

Essayez ceci:

public GroupOfficeDto saveGroupOffice(GroupOfficeDto groupOfficeDto) {
    ...     
    List<GroupOffice> result = officesOfTheGroup.stream()
        .filter(it -> it.getLabel().equals(groupOfficeDto.getLabel()))
        .filter(it -> !it.getId().equals(groupOfficeDto.getId()))
        .collect(Collectors.toList())
    ...
}


1 commentaires

quand j'utilise certains dto.getId et to.getLabel au lieu de London et 5, cela donne une erreur à ce sujet, il doit être définitif .. Comment puis-je utiliser le paramètre au lieu de ces valeurs codées en dur?



5
votes

Si vous avez besoin d'une valeur booléenne, vous pouvez faire:

boolean b = officesOfTheGroup.stream()
    .anyMatch(office -> !office.getId().equals(5) && office.getLabel().equals("London"))


7 commentaires

qu'est-ce que le «bureau» ici? ce n'est pas défini?


@ChrisGarsonn désolé, c'est l'argument lambda. Juste édité


quand j'utilise certains dto.getId et to.getLabel au lieu de London et 5, cela donne une erreur à ce sujet, il doit être définitif .. Comment puis-je utiliser le paramètre au lieu de ces valeurs codées en dur?


La variable utilisée dans l'expression lambda doit être finale ou effectivement finale ... l'erreur est la suivante.


@ChrisGarsonn voir explication finale effective


@ChrisGarsonn attribuez-vous une valeur à groupOfficeDto dans votre méthode avant la boucle?


oui je l'ai assigné comme tu l'as dit efficace final et résolu



2
votes

Y a-t-il une meilleure approche au lieu de parcourir tous les éléments avec la boucle for ?

Notamment, votre code ne parcourt pas tous les éléments s'il en trouve un acceptable avant d'atteindre la fin de la liste. Mais si vous n'avez que la liste avec laquelle travailler, il n'y a pas d'alternative à être prêt à vérifier chaque élément de la liste. Quant à savoir s'il faut utiliser une boucle for , je pense que c'est très bien.

Ou comment puis-je utiliser le flux? Si tel est le cas, est-ce que l'utilisation de stream est une meilleure approche?

Il est en effet assez à la mode ces jours-ci d'utiliser les flux, et bien qu'ils semblent être plus utilisés que je ne le pense, le vôtre n'est pas un cas d'utilisation déraisonnable. Vous pourriez l'écrire comme ceci:

public GroupOfficeDto saveGroupOffice(GroupOfficeDto groupOfficeDto) {     
    List<GroupOffice> officesOfTheGroup = //some list from db..
    Integer officeId = groupOfficeDto.getId();
    String officeLabel = groupOfficeDto.getLabel();

    return officesOfTheGroup.stream()
            .filter(o -> !o.getId().equals(officeId))
            .anyMatch(o -> o.getLabel().equals(officeLabel))
        ? groupOfficeDto : null;
}

L'utilisation du terminal .anyMatch () est particulièrement pertinente ici, car elle permet de terminer le traitement du flux dès que le résultat est déterminé, comme votre boucle for , plutôt que de traiter le flux entier. Notez également que l'ID et l'étiquette avec lesquels vous comparez les bureaux sont extraits et stockés dans des variables avant l'expression de flux. Cela leur permet d'être "effectivement définitifs", comme cela est nécessaire pour qu'ils apparaissent dans les lambdas du flux. Il est également légèrement plus efficace de le faire de cette façon, au lieu de récupérer les mêmes objets du DTO encore et encore - pour le cas de la boucle for également.

Remarque que la version stream n'est pas beaucoup plus simple que la version loop, et pas beaucoup plus facile à lire non plus. Personnellement, je ne vois pas beaucoup d’avantages pour l’un sur l’autre.


2 commentaires

oh il y a une erreur: sur "o.getLabel ()" dans n'importe quelle correspondance, o n'est pas une erreur de variable résolue .. pouvez-vous corriger l'erreur s'il vous plaît?


@ChrisGarsonn, je pense que vous auriez probablement pu le découvrir vous-même, mais c'est une mauvaise forme pour moi de laisser une erreur dans mon code. Fixé.