Фильтр Java 8 Список по самым высоким значениям каждого идентификатора - PullRequest
0 голосов
/ 05 июня 2018

Есть ли способ сделать следующее с функциями Java 8 и лямбдами?

У меня есть этот класс

public class A{
    private String id;
    private int version;
    // getters...
}

Ввод (список упорядочен по id и версиям по возрастанию):

[{"1",1},{"1",2},{"2",1},{"2",2}]

Я хочу иметь список с самыми высокими версиями каждого идентификатора, поэтому результат должен выглядеть следующим образом:

[{"1",2},{"2",2}]

У меня уже есть решение, но мне не нравится, чтомного.Я подумал, может быть, есть лучший способ с Java 8.

static List<A> removeOldVersions(List<A> aList) {
    Map<String, A> map = new HashMap<>();
    aList.forEach(a -> map.put(a.getId(), a));
    return (List<A>) map.values();
}

Ответы [ 3 ]

0 голосов
/ 05 июня 2018

Ну, вы можете собрать в Map и объединить записи через BinaryOperator.maxBy.Как только это будет вычислено, вызовите values (это вернет Collection<A>):

  yourList.stream()
        .collect(Collectors.toMap(
              A::getId,
              Function.identity(),
              BinaryOperator.maxBy(Comparator.comparing(A::getVersion))))
        .values()
0 голосов
/ 05 июня 2018

Введение

Существует два подхода к этому, оба они используют Comparators, я предлагаю вам прочитать о них подробнее по следующей ссылке:

https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html

Я хотел бы показать вам мой самый простой подход без написания вашего собственного фильтра / отдельного алгоритма.В этом решении будет использоваться потоковый API Java 8.

(допустим, вы используете ArrayList или HashSet в обоих примерах.)

Использование потоков

public class Sorter {

    private final class A {
        private String id;
        private int version;

        private A(String id, int version) {
            this.id = id;
            this.version = version;
        }

        public String getId() {
            return id;
        }

        public int getVersion() {
            return version;
        }
    }

    public void sort() {
        final ArrayList<A> list = new ArrayList<A>() {{
            add(new A("1", 1));
            add(new A("1", 2));
            add(new A("2", 1));
            add(new A("2", 2));
        }};

        //Using List as we want to be sure that our List is in order
        list.stream().sorted(Comparator.comparingInt(o -> o.version)).filter(distinctByKey(a -> a.id)).collect(Collectors.toList());
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor)
    {
        Map<Object, Boolean> map = new ConcurrentHashMap<>();
        return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

}

Надеюсь, это ответило на ваш вопрос.

0 голосов
/ 05 июня 2018

Добавьте каждую пару к Map, проверяя, существует ли она и имеет ли меньшее значение перед перезаписью.

Классический подход:

{
    List<A> in = Arrays.asList(new A("'1'", 1),
                               new A("'1'", 2),
                               new A("'2'", 1),
                               new A("'2'", 2));

    Map<String, Integer> map = new LinkedHashMap<>(in.size()); // 'Linked' just keeps the original ordering
    for (A element : in) {
        @Nullable Integer version = map.get(element.id);
        if (version == null || version < element.version)
            map.put(element.id, element.version);
    }

    System.out.println(map);
}

Вывод:

{'1'=2, '2'=2}

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