簡體   English   中英

如何使用Optional和Streams完成任務?

[英]How can I accomplish using Optional and Streams?

public class Product {

    private String name;
    private List<Image> images;
    //getters and setters

      public class Images {
        private String url;
        private List<Thumbnail> thumbnails;

        // getters and setters

        public class Thumbnail{

          //getters and setters
          private String url;
        }
      }
    }
}

我有這門課。 我需要獲取第一個圖像的產品名稱,網址和第一個縮略圖的網址。 我還需要確保產品,圖像和縮略圖都是非空的。

這就是我試圖這樣做的方式:

Optional.ofNullable(product).ifPresent(productData -> {
  response.setProductName(productData.getName());

  Optional.ofNullable(productData.getImages()).ifPresent(images -> {
    images.stream().findFirst().ifPresent(image -> {
      response.setImageUrl(image.getUrl());

        Optional.ofNullable(image.getThumbnails()).ifPresent(thumbnails -> {
        thumbnails.stream().findFirst().ifPresent(thumbnail -> {
          response.getThumbnailUrl();
        });
      });
    });
  });
});

有沒有更好的辦法?

你不應該null列表。 空列表表示相同的事情,而不必引入空檢查。 這可以讓你擺脫兩個ifPresent檢查。

Optional.ofNullable(product).ifPresent(productData -> {
  response.setProductName(productData.getName());

  productData.getImages().stream().findFirst().ifPresent(image -> {
    response.setImageUrl(image.getUrl());

    image.getThumbnails().stream().findFirst().ifPresent(thumbnail -> {
      response.getThumbnailUrl();
    });
  });
});

可選項和流並沒有真正為您帶來任何好處。 不要僅因為存在而使用它們。 考慮使用常規if語句。

if (product == null) {
    return;
}

if (!product.getImages().isEmpty()) {
    Image image = product.getImages().get(0);
    response.setImageUrl(image.getUrl());

    if (!image.getThumbnails().isEmpty()) {
        response.getThumbnailUrl();
    }
}

或者,您可以模擬stream().findFirst().ifPresent()其中for循環在第一次迭代后中斷。

if (product == null) {
    return;
}

for (Image image: product.getImages()) {
    response.setImageUrl(image.getUrl());

    for (Thumbnail thumbnail: image.getThumbnails()) {
        response.getThumbnailUrl();
        break;
    }

    break;
}

@ John的回答是正確的。 如果可以,請返回空列表。

也許你想要區分沒有任何項目而沒有結果(在你的情況下它沒有多大意義,但我們假設是在討論)。 然后返回Optional<List<T>>而不是返回null然后轉換它。 然后@Johannes的回答是正確的。

另一種思考問題的方法是,如果您無法控制返回值,則將其轉換為流以鏈接調用:

Optional.ofNullable(possiblyNullProduct).stream()
  .peek(product -> response.setProductName(product.getName()))
  .map(Product::getImages)
  .filter(Objects::nonNull)
  .map(images -> images.stream().findFirst())
  .filter(Optional::isPresent).map(Optional::get)
  .peek(image -> response.setImageUrl(image.getUrl())
  .map(Image::getThumbnails)
  .filter(Objects::nonNull)
  .map(thumbnails -> thumbnails.stream().findFirst())
  .filter(Optional::isPresent).map(Optional::get)
  .forEach(thumbnail -> response.getThumbnailUrl());

在Java 9中添加了Optional::stream

這只是另一種解決方案,絕不是更好的解決方案。 我歡迎任何關於表現的評論。

獲取每個列表的第一項的另一個選項是轉換為Optional並返回Stream:

  .map(Product::getImages)
  .filter(Objects::nonNull)
  .flatMap(List::stream).findFirst().stream() // <- changed here
  .peek(image -> ...)

你也可以用類似的方式改變最后三行:

  .map(Image::getThumbnails)
  .filter(Objects::nonNull)
  .flatMap(List::stream).findFirst() // <- from here
  .ifPresent(thumbnail -> response.getThumbnailUrl());

是的, flatMap將在這里提供幫助:

Optional<Product> optProduct = Optional.ofNullable(product);
optProduct.ifPresent(p -> response.setProductName(p.getName()));
Optional<Image> optImage = optProduct.flatMap(p -> Optional.ofNullable(p.getImages()))
    .stream().flatMap(il -> il.stream()).findFirst();
optImage.ifPresent(i -> response.setImageUrl(i.getUrl()));
optImage.flatMap(i -> Optional.ofNullable(i.getThumbnails()))
    .stream().flatMap(tl -> tl.stream()).findFirst()
    .ifPresent(t -> response.getThumbnailUrl()); // WTF?

在Java 9中添加了Optional.stream()節點。

我不認為Optionals在這方面有很多幫助。 我會通過抽象迭代邏輯來清理代碼,如下所示:

private <T> void findFirst(List<T> list, Consumer<T> action) {
    if (list != null) {
        list.stream()
            .findFirst()
            .ifPresent(action);
    }
}

if (product != null) {
    response.setProductName(productData.getName());
    findFirst(productData.getImages(), image -> {
        response.setImageUrl(image.getUrl());
        findFirst(image.getThumbnails(), thumbnail -> response.setThumbnailUrl(thumbnail.getUrl()));
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM