java 8嵌套流

Tra*_*iew 13 lambda java-8 java-stream

假设你有这样的结构类:

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;
}
Run Code Online (Sandbox Code Playgroud)

使用Java 8和Streams,我们希望对对象进行过滤idImage并返回Review对象.
可能吗?一个级别很容易,但是我们找不到任何示例或文档的2个级别.

卢声远*_* Lu 16

猜猜你需要什么:(假设吸气剂可用于ReviewRelReviewImage)

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());
Run Code Online (Sandbox Code Playgroud)


tom*_*maj 6

我认为您可以通过不尝试单行代码来获得最可维护和最优雅的代码。:)

当我拥有这些嵌套结构时,我通常会为每个级别创建一个新方法。所以当我编码时,我一次只需要在我的脑海里有一个层次。

尝试将检查是否存在图像的部分拉imageIdPredicate.

一个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));
}
Run Code Online (Sandbox Code Playgroud)

专家提示

如果filterReviews-method 将 thePredicate作为参数,您可以使用相同的方法Review,通过传递不同的Predicates.

  • 在我看来,最好向 `Review` 类添加一个 `hasImage` 方法,该方法只返回简单的旧 `boolean`。然后你可以`.filter(Review::hasImage)`。这也将封装“图像”存储。假设稍后您将 `List&lt;RelReviewImage&gt; images` 更改为 `Map&lt;Integer, RelReviewImage&gt; id2image`。那么`hasImage` 将被简化为`return id2image.containsKey(idImage);` (3认同)