gpt4 book ai didi

java - 两个 ArrayList/List 对象的排序

转载 作者:行者123 更新时间:2023-12-02 01:05:16 25 4
gpt4 key购买 nike

例如,我有两个数组转换为ArrayList,即firstName和lastName。我想使用名字对这两个列表进行排序,姓氏将跟随名字。

预期输出:

firstNameList = {Andrew, Johnson, William}
lastNameList = {Wiggins, Beru, Dasovich};

我的初始计划:

import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;

String [] firstName = {William, Johnson, Andrew};
String [] lastName = {Dasovich, Beru, Wiggins};

//Will convert arrays above into list.
List <String> firstNameList= new ArrayList<String>();
List <String> lastNameList= new ArrayList<String>();

//Conversion
Collections.addAll(firstNameList, firstName);
Collections.addAll(lastNameList, lastName);

最佳答案

域名

正如我在评论中所说,我建议使用 Person -POJO绑定(bind)firstNamelastName以语义方式:

class Person {
public static final String PERSON_TO_STRING_FORMAT = "{f: %s, l: %s}";

private final String firstName;
private final String lastName;

private Person(final String firstName, final String lastName) {
this.firstName = Objects.requireNonNull(firstName);
this.lastName = Objects.requireNonNull(lastName);
}

public static Person of(final String firstName, final String lastName) {
return new Person(firstName, lastName);
}

public String getFirstName() {
return firstName;
}

public String getLastName() {
return lastName;
}

@Override
public String toString() {
return String.format(PERSON_TO_STRING_FORMAT, getFirstName(), getLastName());
}
}

转换两个 String[] firstNameslastNames进入List<Person> ,可以提供一种方法:

    public static List<Person> constructPersons(
final String[] firstNames,
final String[] lastNames) {
if (firstNames.length != lastNames.length) {
throw new IllegalArgumentException("firstNames and lastNames must have same length");
}
return IntStream.range(0, firstNames.length)
.mapToObj(index -> Person.of(firstNames[index], lastNames[index]))
.collect(Collectors.toCollection(ArrayList::new));
}

对该方法的说明:这里,我们使用 collect(Collectors.toCollection(...)) 而不是 collect(Collectors.toList()) 因为我们要对列表进行排序,所以对列表的可变性进行一些控制。

从这里开始有两条通用路线:任一路线都为 Person comparable by public class Person implements Comparable<Person> 或者有人写 Comparator<Person> 。我们将讨论这两种可能性。

<小时/>

挑战

目标是排序Person - 对象。排序的主要标准是人员的名字。如果两个人的名字相同,则应按姓氏排序。名字和姓氏都是 String -对象,应按字典顺序排序,即 String的自然顺序。

<小时/>

解决方案 1:实现 Comparable<Person>Person

实现比较的逻辑很简单:

  1. 比较 firstName两个人使用 equals(...) .
  2. 如果相等,则比较 lastName使用 compareTo(...) 并返回结果。
  3. 否则,比较 firstNamecompareTo(...)并返回结果。

相应的方法将如下所示:

public class Person implements Comparable<Person> {
...
@Override
public final int compareTo(final Person that) {
if (Objects.equals(getFirstName(), that.getFirstName())) {
return getLastName().compareTo(that.getLastName());
}
return getFirstName().compareTo(that.getFirstName());
}
...
}

虽然不是绝对必要的,但建议类的自然顺序(即 Comparable 实现)与其 equals(...) 一致。 -执行。由于现在情况并非如此,我建议覆盖 equals(...) hashCode() :

public class Person implements Comparable<Person> {
...
@Override
public final boolean equals(Object thatObject) {
if (this == thatObject) {
return true;
}
if (thatObject == null || getClass() != thatObject.getClass()) {
return false;
}
final Person that = (Person) thatObject;
return Objects.equals(getFirstName(), that.getFirstName()) &&
Objects.equals(getLastName(), that.getLastName());
}

@Override
public final int hashCode() {
return Objects.hash(getFirstName(), getLastName());
}
...
}

以下代码演示了如何创建和订购 List<Person>从两个String[] :

final List<Person> persons = constructPersons(
new String[]{"Clair", "Alice", "Bob", "Alice"},
new String[]{"Clear", "Wonder", "Builder", "Ace"}
);
Collections.sort(persons);
System.out.println(persons);
<小时/>

解决方案 2:实现 Comparator<Person>

实现挑战部分中给出的排序比较的比较器的传统实现可能如下所示:

class PersonByFirstNameThenByLastNameComparator implements Comparator<Person> {
public static final PersonByFirstNameThenByLastNameComparator INSTANCE =
new PersonByFirstNameThenByLastNameComparator();

private PersonByFirstNameThenByLastNameComparator() {}

@Override
public int compare(final Person lhs, final Person rhs) {
if (Objects.equals(lhs.getFirstName(), rhs.getFirstName())) {
return lhs.getLastName().compareTo(rhs.getLastName());
}
return lhs.getFirstName().compareTo(rhs.getFirstName());
}
}

示例调用可能如下所示:

final List<Person> persons = constructPersons(
new String[]{"Clair", "Alice", "Bob", "Alice"},
new String[]{"Clear", "Wonder", "Builder", "Ace"}
);
persons.sort(PersonByFirstNameThenByLastNameComparator.INSTANCE);
System.out.println(persons);

使用 Java 8,构建 Comparator已通过 Comparator.comparing -API 进行了简化。定义Comparator使用 Comparator.comparing 实现挑战部分中给出的顺序-API,我们只需要一行代码:

Comparator.comparing(Person::getFirstName)
.thenComparing(Person::getLastName)

以下代码演示了 Comparator 是如何实现的用于对 List<Person> 进行排序:

final List<Person> persons = constructPersons(
new String[]{"Clair", "Alice", "Bob", "Alice"},
new String[]{"Clear", "Wonder", "Builder", "Ace"}
);
persons.sort(Comparator.comparing(Person::getFirstName)
.thenComparing(Person::getLastName));
System.out.println(persons);
<小时/>

结束语

一个MRE可在 Ideone 上找到.

我对将名字和姓氏分成两个单独的数组的最初设计决定提出质疑。我选择不包含方法 List<Person> constructPersons(String[] firstNames, String[] lastNames)上课Person因为这只是适配器代码。它应该包含在某个映射器中,但对于 Person 来说不是一个存在的功能。 .

关于java - 两个 ArrayList/List 对象的排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60128651/

25 4 0