Обновление одного объекта из списка с использованием потока - PullRequest
2 голосов
/ 11 апреля 2019

У меня есть список объектов.Мне нужно обновить один объект из списка, который соответствует моему фильтру.Я могу сделать что-то вроде ниже:

List<MyObject> list = list.stream().map(d -> {
    if (d.id == 1) {
        d.name = "Yahoo";
        return d;
    }
    return d;
});

Но меня беспокоит то, что я как бы перебираю весь список, который может содержать до 20 тысяч записей.Я могу сделать for loop, затем break, но этот, я думаю, тоже будет медленным.

Есть ли эффективный способ сделать это?

Ответы [ 3 ]

3 голосов
/ 11 апреля 2019

Используйте findFirst, поэтому после нахождения первого соответствующего элемента в списке остальные элементы не будут обработаны

Optional<MyObject> result = list.stream()
                                .filter(obj->obj.getId()==1)
                                .peek(o->o.setName("Yahoo"))
                                .findFirst();

Или

  //will not return anything but will update the first matching object name

                              list.stream()
                              .filter(obj->obj.getId()==1)
                              .findFirst()
                              .ifPresent(o->o.setName("Yahoo"));
3 голосов
/ 11 апреля 2019

Вы можете использовать карту вместо списка и сохранить идентификатор в качестве ключа.https://docs.oracle.com/javase/8/docs/api/java/util/Map.html

Затем вы можете извлечь его с помощью O(1).

0 голосов
/ 11 апреля 2019

Это зависит от того, как часто вам нужно выполнять эту логику для ваших входных данных.

Если это происходит несколько раз, рассмотрите возможность использования Map, как предложено Raz . Вы также можете преобразовать List в Map, используя Stream:

Map<Integer, MyObject> map = list.stream()
                                 .collect(Collectors.toMap(
                                     MyObject::getId
                                     Function.identity()
                                 ));

Первый аргумент toMap сопоставляет элемент потока с соответствующим ключом на карте (здесь идентификатор MyObject), а второй аргумент сопоставляет элемент со значением карты (здесь сам элемент MyObject) ).

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

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

Если ваши данные уже отсортированы по идентификатору, вы можете использовать бинарный поиск, чтобы быстрее найти ваш элемент.

В противном случае вам нужно перебирать свой список, пока вы не найдете свой предмет. С точки зрения производительности, ничто не будет бить простой цикл здесь. Но использование Stream и Optional, как показано в ответе Deadpool , также подойдет и может привести к более четкому коду, что более важно в большинстве случаев.

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