Stream против Iterator для API с подкачкой - PullRequest
2 голосов
/ 25 апреля 2019

Учитывая веб-API с пейджингом, который возвращает больше элементов, которые могут поместиться в памяти за один раз

HTTP GET /items?start=0&limit=10

Я хочу создать простой в использовании клиент Java.Пейджинговый клиент трудно использовать

PageRequest pageRequest = new PageResut(0,10);
Page<Item> page = client.findItems(page);
while( !page.isLastPage() ) {
   Page<Item> nextPage = client.findItems( page.getNextPage() );
}

Скрытие пейджингового клиента за Iterator ..

Iterator<Item> items = client.pagingItemsIterator();
// every 10 elements the iterator requests the next page behind the scenes i.e.
// the paging code of above is hidden in an iterator
items.forEachRemaining(this::dostuff);

... или Stream упрощает APIиспользование

Stream<Item> items = client.pagingItemsStream();
// every 10 elements the stream requests the next page behind the scenes
// i.e. the paging code above is hidden in the stream supplier
items.forEach(this::dostuff);

A Stream более универсально.Есть ли что-то в том, как поток предназначен для использования, что делает его непригодным для этого варианта использования?Например:

  • Предполагает ли поток, что все элементы известны, по сравнению с запросом следующей закулисной страницы при извлечении последнего элемента в потоке?
  • Это противоречит хорошей практикепотоков, этот элемент # 11 запроса может завершиться с ошибкой RuntimeException, поскольку выполняется запрос новой страницы для получения элементов на следующей странице?

1 Ответ

1 голос
/ 25 апреля 2019

Я хотел сделать это как комментарий, но вроде был слишком большим.

Предполагает ли поток, что все элементы известны ...

Например, посмотрите на Files::lines. Невозможно узнать точное число строк, которыев определенном файле, так что базовая реализация как-то делает это ... Для последовательного потока это легко, для параллельного - все, что они делают, это буферируют, пока не будет буферизовано по крайней мере 1024 строк (+ 1024 в следующем буфере и т. д.на).Так что да, реализация потока без известного размера абсолютно возможна, даже если этот размер может изменяться динамически - хотя это тоже приводит к множеству других проблем, IMO.

Это противоречит передовой практике потоков,что элемент запроса № 11 может завершиться с ошибкой RuntimeException, поскольку выполняется запрос новой страницы для получения элементов на следующей странице?

Не совсем уверен, что я полностью понимаю это, но, похоже, вы обеспокоенынесколько одновременных запросов к одним и тем же данным.Если так, то для меня это не нормально для потоков настолько, насколько это не нормально для просто the PageRequest;В конце концов, вы просто читаете данные - если их там нет, возвращайте пустой список или частичный список или что-то еще, но не бросайте исключение.Если базовый PageRequest выбрасывает это, обработайте его в обертке, которая у вас все равно будет.

Просто обратите внимание, что обычно вы можете очень легко трансформироваться из Iterator -> Stream и Stream -> Iterator, если это необходимо.Тем не менее, я бы придерживался подхода Stream, если бы вы могли его реализовать.

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