java - 如何用最少的代码比较两个字符串列表的java集合?
问题描述
我有两个字符串列表。说,
List1: Element1:汤姆,哈代,十九岁,学生;Element2:约翰,特拉沃尔塔,二十岁,失业;
List2: Element1:约翰,特拉沃尔塔,二十,失业;元素2:汤姆,哈代,十九岁,学生;
我想比较这些列表,并得到列表相同的结果。我可以创建一个包含名称、姓氏、年龄、职业的类“Person”。然后创建对象。但是这些列表来自不同的来源,因此元素对象不会相同。我的意思是 List1 (Tom Hardy) 中的 Element1 与 List2 (Tom Hardy) 中的 Element2 不是同一个对象。我将不得不进入每个元素的(对象)值并比较它们以了解列表是否相同。基本上,我知道如何解决这个问题,我只是想知道如何用最少的代码来完成。
解决方案
是的,您将定义一个Person
类来保存数据的各个部分。
在该类上,您声明它实现Comparable
接口,并使用一个compareTo
方法执行您认为判断两个人相等的任何工作。
然后,您会将这些对象收集Person
到各种列表中。
最后,通过调用它们的List::equals
方法来比较列表,该方法依次调用equals
与每个列表对应的每个元素。
我想比较这些列表,并得到列表相同的结果。
那是 的工作List::equals
。
我可以创建一个包含名称、姓氏、年龄、职业的类“Person”。然后创建对象。
是的。并实现compareTo
&&方法。提示:查看课程。equals
hashCode
Objects
但是这些列表来自不同的来源,因此元素对象不会相同。我的意思是 List1 (Tom Hardy) 中的 Element1 与 List2 (Tom Hardy) 中的 Element2 不是同一个对象。我将不得不进入每个元素的(对象)值并比较它们以了解列表是否相同。
不太清楚你在这里的意思。是不是这些列表可能有代表同一个人但顺序不同的对象?这是一个List::equals
将相同顺序视为列表相等条件的问题。
两种解决方案:
- 在首先检查两个列表是否具有相同大小之后,编写您自己的相等性测试实用程序来搜索第二个列表中的每个项目。
- 种类。
Collections.sort
在调用之前调用两个列表List::equals
。如果要保留它们当前的顺序,请将每个列表复制到新List
对象中;这很快,因为不复制元素对象,只复制对这些元素对象的引用。
我推荐第二种选择,而不是第一种。
基本上,我知道如何解决这个问题,我只是想知道如何用最少的代码来完成。
去做就对了。编写Person
类和&&compareTo
方法。equals
hashCode
没有“最少代码”的问题,这里只是比较字段。使用带有 lambda 语法的 Java 新功能特性可以缩短代码。但是,如果您正在学习 Java,那么短代码不应该是您的目标。编写没有 lambda 的代码可能会更长,但可以帮助您更好地理解正在发生的事情。
进行互联网搜索以找到许多.compareTo
类似于下面的Person
课程。请注意,在我的解释中,我忽略occupation
了平等和比较的考虑。由经理决定的业务规则,而不是程序员的突发奇想,决定了equals
and的含义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
返回计算值的方法。
推荐阅读
- gradle - Sentry log4j2 的 build.gradle 应该包含什么?
- snowflake-cloud-data-platform - 当只有 1 个实例时,雪花 XML 解析不适用于嵌套结构
- r - 对数据框列表进行数字排序
- python - Python中有没有办法根据由语音到文本创建的短文本主题进行段落分割?
- ios - 我有一个 Trimming Video Editor 但在 Xcode 11 之后我收到此错误 No such module 'ABVideoRangeSlider'
- python - 如何删除熊猫数据框中的“镜像复制”行?
- c++ - 带有可变参数模板的表达式模板运算符
- javascript - 在 mapbox 中操作地图
- postgresql - PostgreSQL 的默认用户名和密码是否为 NULL?
- java - 错误原因:org/apache/commons/codec/binary/Base64