web-dev-qa-db-fra.com

java 8 flux imbriqués

Supposons que vous ayez des classes de structure comme celle-ci:

public class Review{
    private Integer idReview;
    private String description;
    private ArrayList<RelReviewImage> images;
}

public class RelReviewImage{
    private Integer idRelReviewImage;
    private Integer idImage;
    private String name;
}

Avec Java 8 et Streams, nous souhaitons faire un filtre pour idImage et renvoyer des objets Review.
C'est possible? Un niveau est facile, mais sur 2 niveaux nous ne trouvons ni exemple ni documentation.

11
TrailRunningReview

Devinez ce dont vous avez besoin: (Supposons que des accesseurs sont disponibles pour Review et RelReviewImage)

List<Review> originalReviews = ...

List<Review> result = originalReviews.stream()
    .filter(review -> review.getImages().stream() //Nested streams. Assume getImages() never null, but empty 
                          .anyMatch(image -> image.getIdImage() == 123)) //'2 level' here
    .collect(Collectors.toList());
15

Je pense que vous pouvez obtenir le code le plus facile à gérer et le plus élégant ici en n’essayant pas d’utiliser une ligne. :)

Lorsque j’ai ces structures imbriquées, j’ai en général crée une nouvelle méthode pour chaque niveau. Ainsi, lorsque je suis en train de coder, je n'ai qu'un niveau à la fois.

Essayez de tirer la partie qui vérifie s'il existe une image avec imageId dans un Predicate.

Une Predicate ici est une Function qui prend votre Review et renvoie une Boolean qui peut être filtrée.

public List<Review> filterReviews(){
    Integer idImage = 1;
    List<Review> reviews = new ArrayList<>();
    ...
    List<Review> result = reviews.stream()
            .filter(hasImage(idImage))
            .collect(Collectors.toList());

    return result;
}

private Predicate<Review> hasImage(final Integer idImage){
    return review -> review.images.stream()
            .anyMatch(image -> Objects.equals(image.idImage, idImage));
}

Protip

Si la méthode filterReviews- a pris la valeur Predicate en tant que paramètre, vous pouvez utiliser la même méthode pour filtrer tous les champs de la variable Review en transmettant Predicates différent.

2
tomaj

Voici quelques idées de base:

public static void main(String[] args) {
    // TODO Auto-generated method stub

    List<Review> reviews = new ArrayList<>();
    for(int i = 0; i < 50; i++) {
        List<RelReviewImage> revImg = new ArrayList<>();
        for(int j = 0; j < 5; j++) {
            revImg.add(new RelReviewImage(j, j, "img_"+j));
        }
        reviews.add(new Review(i, "rev" + i, revImg));
    }

    List<Review> result = reviews.stream().filter(r -> r.getImages().stream().anyMatch(i -> i.getIdImage().intValue() < 2)).collect(Collectors.toList());

}

public class Review {
    private Integer idReview;
    private String description;
    private List<RelReviewImage> images;

    public Review(Integer id, String desc, List<RelReviewImage> img) {
        super();
        this.idReview = id;
        this.description = desc;
        this.images = img;
    }

    public Integer getIdReview() {
        return idReview;
    }

    public void setIdReview(Integer idReview) {
        this.idReview = idReview;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public List<RelReviewImage> getImages() {
        return images;
    }

    public void setImages(List<RelReviewImage> images) {
        this.images = images;
    }
}

public class RelReviewImage {
    private Integer idRelReviewImage;
    private Integer idImage;
    private String name;

    public RelReviewImage(Integer id, Integer id_img, String name) {
        super();
        this.idRelReviewImage = id;
        this.idImage = id_img;
        this.name = name;
    }

    public Integer getIdRelReviewImage() {
        return idRelReviewImage;
    }

    public void setIdRelReviewImage(Integer idRelReviewImage) {
        this.idRelReviewImage = idRelReviewImage;
    }

    public Integer getIdImage() {
        return idImage;
    }

    public void setIdImage(Integer idImage) {
        this.idImage = idImage;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
0
falin

L'exigence indique que vous souhaitez filtrer en fonction de idImage, qui est le champ de notre flux d'images de liste ArrayList.
Étape 1: 

images.stream()
    .filter(idImage->idImage.equals("I123");

Notre objectif sera satisfait si un match est trouvé afin

Étape 2: 

images.stream()
        .filter(idImage->idImage.equals("I123")
        .findAny()//this will return Optional<RelReviewImage> object which will be populated if object is found also need not worry about null condition
        .isPresent()//this will check if the Optional<RelReviewImage> object was populated

Mais d'où provient ce flux d'images? Il est présent dans la classe de relecture afin que l'on puisse dire directement Étape 3

Review myReview-new Review();
            myReview.getImages.stream()
                            .filter(idImage->idImage.equals("I123")
                            .findAny()
                            .isPresent()

Mais nous voulons avoir tous les listOfReviewObjects En supposant que nous ayons ListOfReviewObjects

//Ignore below line of code if not clear,bottomLine is you get list of review objects
            List<Review> reviews = IntStream.rangeClosed(0, 10).mapToObj(e->new Review()).collect(Collectors.toList());

Étape 4

reviews.stream()
            .filter("XYZ condition")
            .collect(Collectors.toList());

Nos critères de filtrage sont conformes à l’étape 2 afin de rassembler chaque pièce que nous avons.

Étape 5

reviews.stream()
        .filter(review->review.getImages().stream()
                                            .filter(relReviewImage->relReviewImage.getIdImage().intValue()==imageId)
                                            .findAny()
                                            .isPresent())
        .collect(Collectors.toList());
0
Sagar