首页 > 解决方案 > 如何用最少的代码比较两个字符串列表的java集合?

问题描述

我有两个字符串列表。说,

我想比较这些列表,并得到列表相同的结果。我可以创建一个包含名称、姓氏、年龄、职业的类“Person”。然后创建对象。但是这些列表来自不同的来源,因此元素对象不会相同。我的意思是 List1 (Tom Hardy) 中的 Element1 与 List2 (Tom Hardy) 中的 Element2 不是同一个对象。我将不得不进入每个元素的(对象)值并比较它们以了解列表是否相同。基本上,我知道如何解决这个问题,我只是想知道如何用最少的代码来完成。

标签: javacollectionscompare

解决方案


是的,您将定义一个Person类来保存数据的各个部分。

在该类上,您声明它实现Comparable接口,并使用一个compareTo方法执行您认为判断两个人相等的任何工作。

然后,您会将这些对象收集Person到各种列表中

最后,通过调用它们的List::equals方法来比较列表,该方法依次调用equals与每个列表对应的每个元素。

我想比较这些列表,并得到列表相同的结果。

那是 的工作List::equals

我可以创建一个包含名称、姓氏、年龄、职业的类“Person”。然后创建对象。

是的。并实现compareTo&&方法。提示:查看课程。equalshashCodeObjects

但是这些列表来自不同的来源,因此元素对象不会相同。我的意思是 List1 (Tom Hardy) 中的 Element1 与 List2 (Tom Hardy) 中的 Element2 不是同一个对象。我将不得不进入每个元素的(对象)值并比较它们以了解列表是否相同。

不太清楚你在这里的意思。是不是这些列表可能有代表同一个人但顺序不同的对象?这是一个List::equals将相同顺序视为列表相等条件的问题。

两种解决方案:

  • 在首先检查两个列表是否具有相同大小之后,编写您自己的相等性测试实用程序来搜索第二个列表中的每个项目。
  • 种类。Collections.sort在调用之前调用两个列表List::equals。如果要保留它们当前的顺序,请将每个列表复制到新List对象中;这很快,因为不复制元素对象,只复制对这些元素对象的引用。

我推荐第二种选择,而不是第一种。

基本上,我知道如何解决这个问题,我只是想知道如何用最少的代码来完成。

去做就对了。编写Person类和&&compareTo方法。equalshashCode

没有“最少代码”的问题,这里只是比较字段。使用带有 lambda 语法的 Java 新功能特性可以缩短代码。但是,如果您正在学习 Java,那么短代码不应该是您的目标。编写没有 lambda 的代码可能会更长,但可以帮助您更好地理解正在发生的事情。

进行互联网搜索以找到许多.compareTo

类似于下面的Person课程。请注意,在我的解释中,我忽略occupation了平等和比较的考虑。由经理决定的业务规则,而不是程序员的突发奇想,决定了equalsand的含义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返回计算值的方法。


推荐阅读