Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как оставить уникальные объекты по полю

Короткий ответ

distinct() сравнивает объекты целиком. Чтобы сравнивать по одному полю, запоминайте уже встреченные значения в Set:

record Order(int id, String customer) {}
 
void main() {
    var orders = List.of(new Order(1, "Anna"), new Order(2, "Oleg"), new Order(3, "Anna"));
 
    var seen = new HashSet<String>();
    var firstPerCustomer = orders.stream().filter(o -> seen.add(o.customer())).toList();
    IO.println(firstPerCustomer);
}

Результат:

[Order[id=1, customer=Anna], Order[id=2, customer=Oleg]]

seen.add() возвращает false для повторного значения, и такой элемент отфильтровывается.

Через toMap

Способ без внешнего состояния: собрать Map по полю и взять значения:

record Order(int id, String customer) {}
 
void main() {
    var orders = List.of(new Order(1, "Anna"), new Order(2, "Oleg"), new Order(3, "Anna"));
 
    var lastPerCustomer = orders.stream()
            .collect(Collectors.toMap(Order::customer, o -> o, (first, second) -> second, LinkedHashMap::new))
            .values();
    IO.println(lastPerCustomer);
}

Результат:

[Order[id=3, customer=Anna], Order[id=2, customer=Oleg]]

Через TreeSet

TreeSet с компаратором по полю считает объекты с одинаковым полем равными:

record Order(int id, String customer) {}
 
void main() {
    var orders = List.of(new Order(1, "Oleg"), new Order(2, "Anna"), new Order(3, "Oleg"));
 
    var unique = new TreeSet<>(Comparator.comparing(Order::customer));
    unique.addAll(orders);
    IO.println(unique);
}

Результат:

[Order[id=2, customer=Anna], Order[id=1, customer=Oleg]]

Частая ошибка

Использовать приём с Set в параллельном потоке. HashSet не потокобезопасен, и результат становится непредсказуемым. В parallelStream() используйте вариант с toMap().

Функции из этого ответа

  • Collectors.toMap() — Сборщик, который строит словарь из элементов потока.
  • Stream.distinct() — Убирает повторяющиеся элементы потока.
  • TreeSet — Множество, которое хранит элементы в отсортированном порядке.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.