Проверьте, имеют ли несколько объектов одинаковое значение поля в java, и удалите дубликаты на основе других полей

#java #arrays #spring-boot #object #arraylist

Вопрос:

Итак, у меня есть список объектов. Предположим, у них есть 2 поля Дата начала, дата окончания(тип данных-отметка времени). Поэтому, если дата начала равна дате начала другого объекта, то я должен выбрать объект с более высокой датой окончания. Как я могу добиться этого эффективно. Я могу использовать 2 для циклов, но это будет иметь высокую временную сложность. Есть ли лучший способ сделать это? Спасибо

Комментарии:

1. Хэш-карта с датой начала в качестве ключа.

2. @user3159253, если возможно, можете ли вы дать фрагмент кода. — Спасибо?

3. Вы можете использовать интерфейс сравнения или компаратора. Ваш класс может реализовать сопоставимый интерфейс и переопределить метод compareTo.

Ответ №1:

Поток по вашему списку, соберите для сопоставления, используя начальную дату ваших объектов в качестве ключа, и используйте функцию слияния, чтобы решить, какой объект сопоставить, если два или более объектов имеют одинаковую начальную дату, сравнивая конечные даты. Что-то вроде:

 Collection<YourObject> result =
            
yourList.stream()
        .collect(Collectors.toMap(YourObject::getStartDate,
                                  Function.identity(),
                                  (a, b) -> a.getEndDate().after(b.getEndDate()) ? a : b))
        .values();
 

Ответ №2:

Вот пример, в котором Integer вместо даты используется для облегчения чтения, но принцип тот же. Просто измените операторы сравнения в соответствии с требованиями и убедитесь, что ваш класс даты можно использовать в качестве ключа карты.

Тестовый класс:

 class Test {
  final Integer start;
  final Integer end;

  public Test(Integer s, Integer e) {
    this.start = s;
    this.end = e;
  }

  @Override
  public String toString() {
    return start   " "   end;
  }
}
 

Пример кода с использованием нескольких экземпляров Test класса:

 List<Test> l = Arrays.asList(new Test(1, 2), new Test(3, 4), new Test(1, 3), new Test(1, 1));

Map<Integer, Test> m = l.stream()
                        .collect(
                            Collectors.toMap(
                                o -> o.start,
                                Function.identity(),
                                (e, r) -> r.end > e.end ? r : e));

m.values().forEach(System.out::println);
 

Выход:

 1 3
3 4
 

Ответ №3:

Вы можете использовать HashMap , например, и воспользоваться преимуществами compute метода:

 hashMap.compute(newObject.getStartDate(), (key, value) -> 
   if (value == null) {
       newObject;
   } else if (value.getEndDate().after(newObject.getEndDate())) {
       value;
   } else {
       newObject;
   }
)