Java Stream с состоянием findFirst - PullRequest
0 голосов
/ 11 октября 2018

Приведенный ниже метод является частью алгоритма взвешенного случайного выбора для выбора песен.

Я хотел бы преобразовать приведенный ниже метод в использование потоков, чтобы решить, будет ли он более четким / предпочтительным.Я не уверен, что это вообще возможно, так как вычисление - это операция с состоянием, зависящая от позиции в списке.

public Song songForTicketNumber(long ticket)
{
    if(ticket<0) return null;
    long remaining = ticket;
    for(Song s : allSongs)  // allSongs is ordered list
    {
        rem-=s.numTickets; // numTickets is a long and never negative
        if(remaining<0)
            return s;
    }
    return null;
}

Более формально: если n - сумма всех Song::numTickets для каждогоSong объект в allSongs, затем для любого целого числа от 0 до n-1, вышеуказанный метод должен вернуть песню в списке.Количество целых чисел, которые будут возвращать конкретный Song объект x, будет определяться как x.numTickets.Критерии выбора для конкретной песни - это диапазон последовательных целых чисел, определяемых и его свойством numTickets и свойством numTickets для каждого элемента в списке слева от него.Как написано в настоящее время, все, что находится за пределами диапазона, будет возвращать нуль.

Примечание. Поведение вне диапазона может быть изменено для размещения потоков (кроме возврата ноля)

1 Ответ

0 голосов
/ 11 октября 2018

Эффективность Stream по сравнению с базовой для или для каждой петли зависит от обстоятельств.В вашем случае весьма вероятно, что Stream будет на меньше эффективнее, чем ваш текущий код, среди прочего, по следующим основным причинам:

  1. Ваша функция с состоянием как вы упомянули.Поддержание состояния с помощью этого метода, вероятно, означает, что нужно использовать какую-то анонимную реализацию BinaryOperator для использования с Stream.reduce, и это станет более объемным и запутанным для чтения, чем ваш текущий код.
  2. Вы замкнуло в вашей токовой петле, и никакая операция Stream не будет отражать такого рода эффективность, особенно учитывая это в сочетании с # 1.
  3. Ваша коллекция заказана, что означает, что поток будет перебирать элементы таким образом, очень похожим на ваш существующий цикл.В зависимости от размера вашей коллекции, вы можете получить некоторую эффективность из parallelStream, но необходимость поддерживать порядок в этом случае будет означать менее эффективный поток.

Единственное реальное преимущество, которое вы можете получить, переключившись на Stream, - это разница в потреблении памяти (вы можете оставить allSongs в памяти и позволить Stream обработать ее более эффективным способом памяти), что нездесь, похоже, применимо.

В заключение, поскольку операции Stream были бы еще более сложными для записи и, вероятно, могли бы нанести вред вашей эффективности, я бы порекомендовал вам не проводить это изменение.

При этом я лично не могу придумать решение на основе Stream, чтобы фактически ответить на ваш вопрос о том, как преобразовать эту работу в Stream.Опять же, это было бы что-то сложное и странное, включающее редуктор или подобное ... (Я удалю этот ответ, если этого недостаточно.)

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