Java 8 использует потоки для различения объектов с дублированным значением поля - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть список объектов.Каждый объект имеет три поля: id, secNumber и type.Type - это перечисление, которое может иметь значения 'new' или 'legacy'.Иногда случается, что в этом списке есть объекты, которые имеют один и тот же secNumber, но другой тип.

в такой ситуации мне нужно удалить тот, который имеет тип 'legacy'.Как это сделать с помощью потоков Java 8?

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Предположим, objects является List<ClassName>, который был объявлен и инициализирован:

List<ClassName> filteredObjects = objects.stream()
    .collect(Collectors.groupingBy(ClassName::getSecNumber))
    .values().stream()
    .flatMap(os -> os.stream().anyMatch(o -> o.getType() == Type.NEW) ?
        os.stream().filter(o -> o.getType() != Type.LEGACY) :
        os.stream()
    ).collect(Collectors.toList());

Я сделал предположение, что объекты типа Type.LEGACY должны быть отфильтрованы, только если существует другой объектвведите Type.NEW, который имеет тот же secNumber.Я также сделал предположение, что вы можете иметь несколько объектов одного и того же type и secNumber и что их, возможно, потребуется сохранить.

Обратите внимание, что collect(Collectors.groupingBy(ClassName::getSecNumber)) возвращает карту любого типа secNumber означает List<ClassName>, поэтому при вызове values() для него возвращается Collection<List<ClassName>>, представляющий коллекцию групп объектов с одинаковыми secNumber.

. Часть flatMap принимает каждую группировку по secNumber, проверяет, имеет ли группировка хотя бы один объект Type.NEW, и, если это так, отфильтровывает объекты типа Type.LEGACY, в противном случае она просто проходит вдоль объектов, которые должны быть сведены в конечный List<ClassName>.Это прежде всего так, что если в группе есть только объекты типа Type.LEGACY, то они не исключаются из окончательной коллекции.

0 голосов
/ 03 декабря 2018

используйте toMap с чем-то вроде этого:

Collection<T> result = list.stream()
    .collect(toMap(T::getSecNumber, 
            Function.identity(), 
             (l, r) -> l.getType() == Type.LEGACY ? r : l))
    .values();

, где T - это класс, который содержит secNumber, id и т. Д.

  • The keyMapper (T::getSecNumber) извлекает каждый secNumber из каждого объекта.
  • valueMapper (Function.identity()) извлекает нужные нам объекты в качестве значений карты, то есть объектов из источника, который они сами.
  • В mergeFunction (l, r) -> мы говорим: «если два заданных объекта имеют одинаковый ключ, то есть getSecNumber, тогда оставьте тот, где их тип равен« NEW », и отбросьте тот, у которого« LEGACY »», инаконец, мы вызываем values() для накопления значений карты в Коллекции.

Редактировать:

после комментария @Tomer Aberbach, который вы, возможно, ищете:

List<T> result = 
            list.stream()
                .collect(groupingBy(T::getSecNumber))
                .values()
                .stream()
                .flatMap(l -> l.stream().anyMatch(e -> e.getType() == Type.NEW) ?
                    l.stream().filter(e -> e.getType() != Type.LEGACY) :
                    l.stream())
                .collect(toList());

Первое решение, использующее toMap, предполагает, что не может быть нескольких объектов с одинаковыми secNumber и type.

...