Java 8 вложенных потоков
Предположим, что у вас есть структурные классы:
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;
}
С Java 8 и Stream
мы хотим сделать фильтр для idImage
и вернуть объекты Review
.
Является ли это возможным? Один уровень прост, но 2 уровня мы не можем найти ни одного примера или документации.
Ответы
Ответ 1
Угадайте, что вам нужно: (Предположите, что геттеры доступны для Review
и 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());
Ответ 2
Я думаю, вы можете получить самый удобный и элегантный код здесь, не пытаясь сделать однострочный.:)
Когда у меня есть эти вложенные структуры, я обычно создаю новый метод для каждого уровня. Поэтому, когда я кодирую, мне нужно иметь только один уровень в голове.
Попробуйте потянуть деталь, которая проверяет, существует ли изображение с imageId
в Predicate
.
A Predicate
здесь Function
, который принимает ваш Review
и возвращает Boolean
, который можно отфильтровать.
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
Если метод filterReviews
принял параметр Predicate
в качестве параметра, вы можете использовать тот же метод для фильтрации по всем различным полям внутри Review
, передав разные Predicates
.
Ответ 3
Вот несколько основных идей:
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;
}
}