Как переписать его с помощью потокового API - PullRequest
0 голосов
/ 03 июня 2018

Я не знаю всех возможностей Stream API.

Моя задача: у меня есть список строк с URL-адресами, и у меня есть другой список моих пользовательских объектов с двумя методами

String videoFromUrl(String url);


boolean support(String url);

Я должен выбрать URL из первого списка, который будет поддерживаться одним экземпляром второго списка, а затем вернуть преобразованный URL

Мой код:

@Override
    protected String videoSourceFromDocument(final Document document) {
        final List<String> hrefs = ...;
        for (final String href : hrefs) {
            final Optional<VideoDownloader> videoDownloader = this.videoDownloaders/*this is my second list*/
                                                                  .stream()
                                                                  .filter(dwnldr->dwnldr.support(href))
                                                                  .findFirst();
            if(videoDownloader.isPresent()){
                return videoDownloader.get().videoFromUrl(href);
            }
        }
        this.logger().warn("Url {} doesn't has video source",document.baseUri());
        throw new IllegalArgumentException();
    }

Это лучший способпереписать его с помощью Stream API?

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Вы можете заменить цикл for конвейером Stream, используя несколько Optional методов:

return hrefs.stream() // Stream<String>
            .map(href -> this.videoDownloaders
                             .stream() // Stream<VideoDownloader>
                             .filter(dwnldr->dwnldr.support(href))
                             .findFirst() // Optional<VideoDownloader>
                             .map(dwnldr -> dwnldr.videoFromUrl(href))) // Stream<Optional<String>>
            .filter(Optional::isPresent) // keep only the non-empty Optionals
            .findFirst() // Optional<Optional<String>>
            .orElseThrow(IllegalArgumentException::new) // Optional<String>
            .get(); // String
0 голосов
/ 03 июня 2018

Когда вам нужно два внутренних цикла, чтобы сделать что-то обязательным образом, решение сделать то же самое с помощью потоков - это обычно использовать flatMap:

protected String videoSourceFromDocument(final Document document) {
    final List<String> hrefs = ...;
    return hrefs.stream()
                .flatMap(href -> this.videoDownloaders.stream()
                                     .filter(d -> d.support(href))
                                     .map(d -> d.videoFromUrl(href)))
                .findFirst()
                .orElseThrow(() -> {
                    this.logger().warn("Url {} doesn't has video source", document.baseUri());
                    return new IllegalArgumentException();
                });
}

Я бы удалил журнал, хотя,и поместите информативное сообщение в IllegalArgumentException.Или просто верните Optional<String>, чтобы вызывающий мог решить, что делать, когда нет источника видео.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...