例如,我有两个数组转换为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)firstName
和lastName
以语义方式:
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[]
firstNames
和lastNames
进入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
实现比较的逻辑很简单:
- 比较
firstName
两个人使用equals(...)
. - 如果相等,则比较
lastName
使用compareTo(...)
并返回结果。 - 否则,比较
firstName
与compareTo(...)
并返回结果。
相应的方法将如下所示:
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);
<小时/>
结束语
我对将名字和姓氏分成两个单独的数组的最初设计决定提出质疑。我选择不包含方法 List<Person> constructPersons(String[] firstNames, String[] lastNames)
上课Person
因为这只是适配器代码。它应该包含在某个映射器中,但对于 Person
来说不是一个存在的功能。 .
关于java - 两个 ArrayList/List 对象的排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60128651/