Да, вы бы задали класс Person
для хранения частей данных.
В этом классе вы объявляете его для реализации интерфейса Comparable
с compareTo
метод выполнения любой работы, которую вы считаете равным.
Затем вы должны собрать эти Person
объекты в различные списки .
И, наконец, сравните списки, вызвав их метод List::equals
, который в свою очередь вызывает equals
для каждого элемента, соответствующего каждому списку.
Я хочусравнить эти списки и получить результат, что списки идентичны.
Это работа List::equals
.
Я мог бы создать класс "Person" с полями имя, фамилия, возраст, род занятий,Затем создайте объекты.
Да. И реализовать методы compareTo
& equals
& hashCode
. Совет: См. Класс Objects
.
Но эти списки происходят из разных источников, поэтому объекты-элементы не будут одинаковыми. Я имею в виду, что Элемент1 из Списка1 (Том Харди) не будет тем же объектом, что и Элемент2 из Списка2 (Том Харди). Я должен был бы пойти в значения каждого элемента (объекта) и сравнить их, чтобы узнать, идентичны ли списки.
Не совсем уверен, что вы имеете в виду здесь. Неужели списки могут содержать объекты, представляющие тех же лиц, но в другом порядке? Это проблема для List::equals
, который рассматривает один и тот же порядок как условие равенства списков.
Два решения:
- Напишите свою собственную утилиту проверки равенства для поиска второгосписок для каждого элемента в первом, после первой проверки, что оба списка имеют одинаковый размер.
- Сортировка. Позвоните
Collections.sort
в оба списка, прежде чем звонить List::equals
. Если вы хотите сохранить их текущий порядок, скопируйте каждый список в новые List
объекты;это быстро, поскольку объекты элементов не копируются, копируются только ссылки на эти объекты элементов.
Я рекомендую второй вариант, а не первый.
В принципе, я знаю, как решить эту проблему, мне просто интересно, как это можно сделать с наименьшим количеством кода.
Просто сделайте это. Напишите класс Person
и методы compareTo
& equals
& hashCode
.
Нет вопроса "наименьшего кода", здесь только сравнение полей. Использование новых функциональных возможностей Java с лямбда-синтаксисом может сократить код. Но короткий код должен не быть вашей целью, если вы изучаете Java. Написание кода без лямбд, скорее всего, займет больше времени, но может помочь вам лучше понять, что происходит.
Выполните поиск в Интернете, чтобы найти множество примеров compareTo
.
Что-то вроде следующего Person
класса. Обратите внимание, как в моей интерпретации я опускаю occupation
из соображений равенства и сравнения. Бизнес-правила, определяемые менеджером, а не прихотями программиста, определяют значение equals
и compareTo
. Кстати, помните, что hashCode
должен соответствовать логике equals
.
package work.basil.example;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.Comparator;
import java.util.Objects;
public class Person implements Comparable < Person >
{
// Statics
private static final Comparator < Person > NATURAL_ORDER_COMPARATOR =
Comparator
.comparing( Person :: getDateOfBirth )
.thenComparing( Person :: getGivenName )
.thenComparing( Person :: getSurname );
// Members
private String givenName, surname;
private LocalDate dateOfBirth;
private String occupation;
// Constructor
public Person ( String givenName , String surname , LocalDate dateOfBirth , String occupation )
{
Objects.requireNonNull( givenName );
Objects.requireNonNull( surname );
Objects.requireNonNull( dateOfBirth );
Objects.requireNonNull( occupation );
this.givenName = givenName;
this.surname = surname;
this.dateOfBirth = dateOfBirth;
this.occupation = occupation;
}
// `Comparable` interface
public int compareTo ( Person other )
{
return NATURAL_ORDER_COMPARATOR.compare( this , other );
}
// `Object` overrides
@Override
public boolean equals ( Object o )
{
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
Person person = ( Person ) o;
return getGivenName().equals( person.getGivenName() ) &&
getSurname().equals( person.getSurname() ) &&
getDateOfBirth().equals( person.getDateOfBirth() );
}
@Override
public int hashCode ( )
{
return Objects.hash( getGivenName() , getSurname() , getDateOfBirth() );
}
@Override
public String toString ( )
{
return "Person{" +
"givenName='" + this.getGivenName() + '\'' +
" | surname='" + this.getSurname() + '\'' +
" | dateOfBirth=" + this.getDateOfBirth() +
" | occupation='" + this.getOccupation() + '\'' +
'}';
}
// Accessors
public String getGivenName ( )
{
return givenName;
}
public String getSurname ( )
{
return surname;
}
public LocalDate getDateOfBirth ( )
{
return dateOfBirth;
}
public String getOccupation ( )
{
return occupation;
}
public int age ( ZoneId zoneId )
{
Objects.requireNonNull( zoneId );
LocalDate today = LocalDate.now( zoneId );
Period period = Period.between( this.getDateOfBirth() , today );
return period.getYears() ;
}
}
и некоторому примеру использования.
У нас есть два списка с одинаковыми объектами, но разным порядком. Мы сравниваем их как есть и после сортировки. Для удобства программиста мы используем потоки для сортировки. Обратите внимание, что потоки могут быть медленнее, чем обычные подходы, но вряд ли могут быть проблемой.
List < Person > thesePeople = List.of(
new Person( "Tom" , "Hardy" , LocalDate.of( 1984 , Month.JANUARY , 23 ) , "Student" ) ,
new Person( "John" , "Travolta" , LocalDate.of( 1965 , Month.MARCH , 17 ) , "Unemployed" )
);
List < Person > thosePeople = List.of(
new Person( "John" , "Travolta" , LocalDate.of( 1965 , Month.MARCH , 17 ) , "Unemployed" ),
new Person( "Tom" , "Hardy" , LocalDate.of( 1984 , Month.JANUARY , 23 ) , "Student" )
);
boolean givenListsAreEqual = thesePeople.equals( thosePeople );
boolean sortedListsAreEqual = thesePeople.stream().sorted().collect( Collectors.toList() ).equals( thosePeople.stream().sorted().collect( Collectors.toList() ) );
System.out.println( "givenListsAreEqual = " + givenListsAreEqual );
System.out.println( "sortedListsAreEqual = " + sortedListsAreEqual );
GivenListsAreEqual = false
sortedListsAreEqual = true
Кстати, вы увидите, что я храню дату рождения. Хранение возраста не имеет смысла, так как возраст может меняться изо дня в день. У меня есть age
метод для возврата вычисленного значения.