我有两个字符串列表。说
-
列表1:元素1:汤姆,哈代,十九岁,学生; 元素2:约翰,特拉沃尔塔,二十岁,失业;
-
列表2: 元素1:约翰,特拉沃尔塔,二十岁,失业; 元素2:汤姆,哈代,十九岁,学生;
我想比较这些列表,并得到列表相同的结果。 我可以创建一个带有字段名称、姓氏、年龄、职业的类"人"。然后创建对象。但是这些列表来自不同的来源,因此,元素对象不会相同。我的意思是List1(Tom Hardy(中的Element1与List2(Tom Hardy(中的Element2不是同一个对象。我必须进入每个元素(对象的(值并比较它们以了解列表是否相同。 基本上,我知道如何解决这个问题,我只是想知道如何用最少的代码完成此操作。
是的,您可以定义一个Person
类来保存数据的各个部分。
在该类上,您声明它以实现Comparable
接口,并使用compareTo
方法执行您认为判断两个人相等的任何工作。
然后,您可以将这些Person
对象收集到各个列表中。
最后,通过调用列表的List::equals
方法来比较列表,该方法又对对应于每个列表的每个元素调用equals
。
我想比较这些列表,并得到列表相同的结果。
那是List::equals
的工作。
我可以创建一个带有字段名称、姓氏、年龄、职业的类"人"。然后创建对象。
是的。并实施compareTo
&equals
&hashCode
方法。提示:请参阅Objects
类。
但是这些列表来自不同的来源,因此,元素对象不会相同。我的意思是List1(Tom Hardy(中的Element1与List2(Tom Hardy(中的Element2不是同一个对象。我必须进入每个元素(对象的(值并比较它们以了解列表是否相同。
不太确定你在这里的意思。是不是名单上有代表同一个人但顺序不同的对象?对于List::equals
来说,这是一个问题,他们认为相同的顺序是列表平等的条件。
两种解决方案:
- 编写您自己的相等性测试实用程序,以便在第一个列表中搜索第一个项目中的每个项目,首先检查两个列表是否具有相同的大小。
- 排序。在呼叫
List::equals
之前呼叫两个列表中的Collections.sort
。如果要保留其当前顺序,请将每个列表复制到新的List
对象中;这很快,因为不会复制元素对象,只会复制对这些元素对象的引用。
我推荐第二种选择,而不是第一种。
基本上,我知道如何解决这个问题,我只是想知道如何用最少的代码完成此操作。
只管去做。编写Person
类和compareTo
&equals
&hashCode
方法。
没有"最少代码"的问题,这里只是比较字段。将Java的新功能特性与lambda语法一起使用可以缩短代码。但是,如果您正在学习Java,短代码不应该是您的目标。在没有 lambda 的情况下编写代码可能会更长,但可以帮助您更好地了解正在发生的事情。
做互联网搜索以找到许多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 );
给定列表是相等的 = 假
sortedListsAreEqual = true
顺便说一下,你会看到我存储了出生日期。存储年龄是没有意义的,因为年龄可能每天都在变化。我有age
方法来返回计算值。
我想出的最少代码解决方案:
public static void main(String[] args) {
List<List<String>> list1 = Arrays.asList(
Arrays.asList("Tom", "Hardy", "nineteen", "student"),
Arrays.asList("John", "Travolta", "twenty", "unemployed"));
List<List<String>> list2 = Arrays.asList(
Arrays.asList("Tom", "Hardy", "nineteen", "student"),
Arrays.asList("John", "Travolta", "twenty", "unemployed"));
List<String> thesePeople = separatePropertiesToBigSinglePropertySortedList(list1);
List<String> thosePeople = separatePropertiesToBigSinglePropertySortedList(list2);
System.out.println("sortedListsAreEqual = " + thesePeople.equals(thosePeople));
}
private static List<String> separatePropertiesToBigSinglePropertySortedList(List<List<String>> listWithSeparateProperties) {
List<String> resultList = new ArrayList<String>();
for (List<String> propertiesOfPerson : listWithSeparateProperties) {
String bigSingleProperty = "";
for (String property : propertiesOfPerson) {
bigSingleProperty = bigSingleProperty + property;
}
resultList.add(bigSingleProperty);
}
Collections.sort(resultList);
return resultList;
}