Сравните значения полей объекта в списке массивов на основе условий и удалите, если условие истинно - PullRequest
0 голосов
/ 05 декабря 2018

Предположим, это классы Java-бина -

class Camp {
      int number;
      User userId;
      Date createDt;
 }

class User {
  private String id;
  private String name;
}

Я хочу удалить те записи из arrayList типа Camp, которые имеют тот же userId, но меньший createDt.

Предположим, что этосписок -

// ... the list is already populated
List<Camp> usersList = populatedListOfUser();

И это метод -

private List<Camp> skipByComparison(List<Camp> usersList){
    List<Camp> mainList = new ArrayList<Camp>();
    Set<Camp> s = new TreeSet<Camp>(new Comparator<Camp>() {

        @Override
        public int compare(Camp o1, Camp o2) {
            if(o1.getUserId().getId().equals(o2.getUserId().getId())) {
                if(o1.getCreatedTs().compareTo(o2.getCreatedTs()) < 0) {
                    usersList.remove(o1);
                    return -1;
                } else {
                    return 1;
                }
            } else {
                return 0;
            }
        }
    });
    s.addAll(usersList);
    mainList.addAll(s);
}

Так что, когда я вызываю -

usersList = skipByComparison(usersList);

, я не получаю записи из arrayListтипа Camp с тем же идентификатором пользователя, но меньшим createDt.

Например,если у меня есть 2 записи с одинаковым Camp.getUser().getId(), но record 1 имеет CreateDt больше record 2, тогда я хочу удалить record 2.

Ответы [ 2 ]

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

Вы можете использовать toMap сборщик:

Collection<Camp> values = usersList.stream()
                .collect(toMap(c -> c.getUser().getId(),
                        Function.identity(),
                        BinaryOperator.maxBy(Comparator.comparing(Camp::getCreateDt))))
                .values();

см. Этот ответ для объяснения того, как работает карта

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

Вы можете обновить свой код как:

private List<Camp> skipByComparison(List<Camp> usersList){
    Set<Camp> s = new TreeSet<>((o1, o2) -> o1.getUserId().getId().equals(o2.getUserId().getId()) ? 
            o1.getCreateDt().compareTo(o2.getCreateDt()) : 0);
    s.addAll(usersList);
    return new ArrayList<>(s);
}

или лучше, вы можете использовать Collectors и потоки, чтобы решить его как:

private List<Camp> skipByComparisonStream(List<Camp> usersList) {
    return new ArrayList<>(usersList.stream()
            .collect(Collectors.toMap(c -> c.getUserId().getId(),
                    Function.identity(),
                    (a, b) -> a.getCreateDt().after(b.getCreateDt()) ? a : b))
            .values());
}

Объяснение : Ваш Comparator в настоящее время не возвращает никакого значения для случая, когда две даты могут быть equal, вам, вероятно, следует просто положиться на реализацию compareTo класса Date для этого:

Set<Camp> s = new TreeSet<>(new Comparator<Camp>() {
    @Override
    public int compare(Camp o1, Camp o2) {
        return o1.getUserId().getId().equals(o2.getUserId().getId()) 
                ? o1.getCreateDt().compareTo(o2.getCreateDt()) : 0;
    }
});

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

Set<Camp> s = new TreeSet<>((o1, o2) -> o1.getUserId().getId().equals(o2.getUserId().getId())
        ? o1.getCreateDt().compareTo(o2.getCreateDt()) : 0);

Остальное, что я сделал, - это упростил порядок выполнения и очистил избыточную инициализацию.

В сторону : Я только что получил исправление в другом вопросе и рекомендую вам также использовать java.time.LocalDate для атрибута createDt.

...