ฉันมีวัตถุperson (int age; String name;)
มากมาย
ฉันจะเรียงลำดับอาร์เรย์ตามตัวอักษรตามชื่อแล้วตามอายุได้อย่างไร
อัลกอริทึมใดที่คุณจะใช้สำหรับสิ่งนี้
ฉันมีวัตถุperson (int age; String name;)
มากมาย
ฉันจะเรียงลำดับอาร์เรย์ตามตัวอักษรตามชื่อแล้วตามอายุได้อย่างไร
อัลกอริทึมใดที่คุณจะใช้สำหรับสิ่งนี้
คำตอบ:
คุณสามารถใช้Collections.sort
ดังต่อไปนี้:
private static void order(List<Person> persons) {
Collections.sort(persons, new Comparator() {
public int compare(Object o1, Object o2) {
String x1 = ((Person) o1).getName();
String x2 = ((Person) o2).getName();
int sComp = x1.compareTo(x2);
if (sComp != 0) {
return sComp;
}
Integer x1 = ((Person) o1).getAge();
Integer x2 = ((Person) o2).getAge();
return x1.compareTo(x2);
}});
}
List<Persons>
ตอนนี้ถูกจัดเรียงตามชื่อจากนั้นตามอายุ
String.compareTo
"เปรียบเทียบสองสาย lexicographically" - จากเอกสาร
Collections.sort
เป็นวิธีการคงที่ในห้องสมุดคอลเลกชันพื้นเมือง การเรียงลำดับตามจริงนั้นคุณเพียงแค่ต้องทำการจัดเรียงตัวเปรียบเทียบซึ่งกำหนดว่าควรจะเปรียบเทียบองค์ประกอบสองอย่างในรายการของคุณอย่างไร: สิ่งนี้ทำได้โดยการให้compare
วิธีการใช้งานของคุณเอง
Comparable
แล้วมีชั้นวัตถุของตัวเองก็จะทำให้รู้สึกมากขึ้นในการดำเนินการ ดูคำตอบโดย @ berry120
Comparator<Person> comparator = Comparator.comparing(Person::getName).thenComparingInt(Person::getAge);
สำหรับผู้ที่สามารถใช้ Java 8 สตรีมมิ่ง API ได้มีวิธีการเรียงต่อกันที่จัดทำเป็นเอกสารไว้ที่นี่: Lambdas และการเรียงลำดับ
ฉันกำลังมองหาเทียบเท่าของ C # LINQ:
.ThenBy(...)
ฉันพบกลไกใน Java 8 บน Comparator:
.thenComparing(...)
ดังนั้นนี่คือตัวอย่างข้อมูลที่แสดงให้เห็นถึงอัลกอริทึม
Comparator<Person> comparator = Comparator.comparing(person -> person.name);
comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));
ลองดูลิงค์ด้านบนเพื่อดูวิธีการเรียงลำดับและคำอธิบายเกี่ยวกับวิธีการอนุมานประเภทของ Java ทำให้การกำหนดมากกว่า clunky เปรียบเทียบกับ LINQ
นี่คือการทดสอบหน่วยเต็มรูปแบบสำหรับการอ้างอิง:
@Test
public void testChainedSorting()
{
// Create the collection of people:
ArrayList<Person> people = new ArrayList<>();
people.add(new Person("Dan", 4));
people.add(new Person("Andi", 2));
people.add(new Person("Bob", 42));
people.add(new Person("Debby", 3));
people.add(new Person("Bob", 72));
people.add(new Person("Barry", 20));
people.add(new Person("Cathy", 40));
people.add(new Person("Bob", 40));
people.add(new Person("Barry", 50));
// Define chained comparators:
// Great article explaining this and how to make it even neater:
// http://blog.jooq.org/2014/01/31/java-8-friday-goodies-lambdas-and-sorting/
Comparator<Person> comparator = Comparator.comparing(person -> person.name);
comparator = comparator.thenComparing(Comparator.comparing(person -> person.age));
// Sort the stream:
Stream<Person> personStream = people.stream().sorted(comparator);
// Make sure that the output is as expected:
List<Person> sortedPeople = personStream.collect(Collectors.toList());
Assert.assertEquals("Andi", sortedPeople.get(0).name); Assert.assertEquals(2, sortedPeople.get(0).age);
Assert.assertEquals("Barry", sortedPeople.get(1).name); Assert.assertEquals(20, sortedPeople.get(1).age);
Assert.assertEquals("Barry", sortedPeople.get(2).name); Assert.assertEquals(50, sortedPeople.get(2).age);
Assert.assertEquals("Bob", sortedPeople.get(3).name); Assert.assertEquals(40, sortedPeople.get(3).age);
Assert.assertEquals("Bob", sortedPeople.get(4).name); Assert.assertEquals(42, sortedPeople.get(4).age);
Assert.assertEquals("Bob", sortedPeople.get(5).name); Assert.assertEquals(72, sortedPeople.get(5).age);
Assert.assertEquals("Cathy", sortedPeople.get(6).name); Assert.assertEquals(40, sortedPeople.get(6).age);
Assert.assertEquals("Dan", sortedPeople.get(7).name); Assert.assertEquals(4, sortedPeople.get(7).age);
Assert.assertEquals("Debby", sortedPeople.get(8).name); Assert.assertEquals(3, sortedPeople.get(8).age);
// Andi : 2
// Barry : 20
// Barry : 50
// Bob : 40
// Bob : 42
// Bob : 72
// Cathy : 40
// Dan : 4
// Debby : 3
}
/**
* A person in our system.
*/
public static class Person
{
/**
* Creates a new person.
* @param name The name of the person.
* @param age The age of the person.
*/
public Person(String name, int age)
{
this.age = age;
this.name = name;
}
/**
* The name of the person.
*/
public String name;
/**
* The age of the person.
*/
public int age;
@Override
public String toString()
{
if (name == null) return super.toString();
else return String.format("%s : %d", this.name, this.age);
}
}
Comparator<Person> comparator = Comparator.comparing(Person::getName).thenComparing(Person::getAge);
thenComparingInt
สำหรับอายุ (int)
Collections.sort(people, comparator);
แทนได้หรือไม่?
ใช้วิธีการของ Java 8 Streams ...
//Creates and sorts a stream (does not sort the original list)
persons.stream().sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
และแนวทางของ Java 8 Lambda ...
//Sorts the original list Lambda style
persons.sort((p1, p2) -> {
if (p1.getName().compareTo(p2.getName()) == 0) {
return p1.getAge().compareTo(p2.getAge());
} else {
return p1.getName().compareTo(p2.getName());
}
});
สุดท้าย ...
//This is similar SYNTAX to the Streams above, but it sorts the original list!!
persons.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
คุณจำเป็นต้องใช้งานของคุณเองComparator
แล้วใช้มันตัวอย่างเช่น
Arrays.sort(persons, new PersonComparator());
เครื่องมือเปรียบเทียบของคุณอาจมีลักษณะเช่นนี้:
public class PersonComparator implements Comparator<? extends Person> {
public int compare(Person p1, Person p2) {
int nameCompare = p1.name.compareToIgnoreCase(p2.name);
if (nameCompare != 0) {
return nameCompare;
} else {
return Integer.valueOf(p1.age).compareTo(Integer.valueOf(p2.age));
}
}
}
ตัวเปรียบเทียบจะเปรียบเทียบชื่อก่อนหากไม่เท่ากับจะส่งคืนผลลัพธ์จากการเปรียบเทียบมิฉะนั้นจะส่งคืนผลลัพธ์การเปรียบเทียบเมื่อเปรียบเทียบอายุของบุคคลทั้งสอง
รหัสนี้เป็นเพียงแบบร่าง: เนื่องจากคลาสนั้นไม่เปลี่ยนรูปคุณสามารถนึกถึงการสร้างซิงเกิลตันของมันแทนที่จะสร้างอินสแตนซ์ใหม่สำหรับการเรียงลำดับแต่ละครั้ง
คุณสามารถใช้วิธี Java 8 Lambda เพื่อทำสิ่งนี้ แบบนี้:
persons.sort(Comparator.comparing(Person::getName).thenComparing(Person::getAge));
ให้คลาสบุคคลของคุณนำไปใช้งานComparable<Person>
และจากนั้นใช้วิธีการเปรียบเทียบกับตัวอย่างเช่น:
public int compareTo(Person o) {
int result = name.compareToIgnoreCase(o.name);
if(result==0) {
return Integer.valueOf(age).compareTo(o.age);
}
else {
return result;
}
}
ที่จะเรียงลำดับตามชื่อ (กรณีตาย) และตามอายุ จากนั้นคุณสามารถเรียกใช้Arrays.sort()
หรือCollections.sort()
บนคอลเลกชันหรืออาร์เรย์ของวัตถุบุคคล
Guava's ComparisonChain
ให้วิธีที่สะอาดในการทำ อ้างอิงถึงลิงค์นี้
ยูทิลิตี้สำหรับการดำเนินการคำสั่งเปรียบเทียบที่ถูกผูกมัด ตัวอย่างเช่น:
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(this.aString, that.aString)
.compare(this.anInt, that.anInt)
.compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
.result();
}
คุณสามารถทำสิ่งนี้:
List<User> users = Lists.newArrayList(
new User("Pedro", 12),
new User("Maria", 10),
new User("Rafael",12)
);
users.sort(
Comparator.comparing(User::getName).thenComparing(User::getAge)
);
ใช้Comparator
แล้วใส่วัตถุเข้าไปCollection
แล้วCollections.sort();
class Person {
String fname;
String lname;
int age;
public Person() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public Person(String fname, String lname, int age) {
this.fname = fname;
this.lname = lname;
this.age = age;
}
@Override
public String toString() {
return fname + "," + lname + "," + age;
}
}
public class Main{
public static void main(String[] args) {
List<Person> persons = new java.util.ArrayList<Person>();
persons.add(new Person("abc3", "def3", 10));
persons.add(new Person("abc2", "def2", 32));
persons.add(new Person("abc1", "def1", 65));
persons.add(new Person("abc4", "def4", 10));
System.out.println(persons);
Collections.sort(persons, new Comparator<Person>() {
@Override
public int compare(Person t, Person t1) {
return t.getAge() - t1.getAge();
}
});
System.out.println(persons);
}
}
สร้างเครื่องมือเปรียบเทียบให้มากที่สุดเท่าที่จำเป็น หลังจากนั้นให้เรียกวิธีการ "thenComparing" สำหรับแต่ละหมวดหมู่คำสั่งซื้อ มันเป็นวิธีการของ Streams ดู:
//Sort by first and last name
System.out.println("\n2.Sort list of person objects by firstName then "
+ "by lastName then by age");
Comparator<Person> sortByFirstName
= (p, o) -> p.firstName.compareToIgnoreCase(o.firstName);
Comparator<Person> sortByLastName
= (p, o) -> p.lastName.compareToIgnoreCase(o.lastName);
Comparator<Person> sortByAge
= (p, o) -> Integer.compare(p.age,o.age);
//Sort by first Name then Sort by last name then sort by age
personList.stream().sorted(
sortByFirstName
.thenComparing(sortByLastName)
.thenComparing(sortByAge)
).forEach(person->
System.out.println(person));
ดู: เรียงลำดับวัตถุที่ผู้ใช้กำหนดบนหลายฟิลด์ - Comparator (แลมบ์ดาสตรีม)
ฉันจะระมัดระวังเมื่อใช้ Guava ComparisonChain
เพราะมันสร้างอินสแตนซ์ของมันต่อองค์ประกอบถูกนำมาเปรียบเทียบดังนั้นคุณจะได้ดูการสร้างของN x Log N
กลุ่มเปรียบเทียบเพื่อเปรียบเทียบถ้าคุณกำลังเรียงลำดับหรือN
อินสแตนซ์ถ้าคุณทำซ้ำและตรวจสอบความเท่าเทียมกัน
ฉันจะสร้างสแตติกแทนComparator
โดยใช้ Java 8 API ใหม่ล่าสุดหากเป็นไปได้หรือOrdering
API ของ Guava ที่อนุญาตให้คุณทำนี่คือตัวอย่างของ Java 8:
import java.util.Comparator;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.nullsLast;
private static final Comparator<Person> COMPARATOR = Comparator
.comparing(Person::getName, nullsLast(naturalOrder()))
.thenComparingInt(Person::getAge);
@Override
public int compareTo(@NotNull Person other) {
return COMPARATOR.compare(this, other);
}
นี่คือวิธีใช้Ordering
API ของ Guava : https://github.com/google/guava/wiki/OrderingExplained
compare
วิธีการไม่ได้สร้างอะไร แต่ผลตอบแทนหนึ่งอินสแตนซ์เดี่ยวLESS
, GREATER
หรือACTIVE
ขึ้นอยู่กับผลของการเปรียบเทียบ นี่เป็นวิธีการที่ได้รับการปรับให้เหมาะสมที่สุดและจะไม่เพิ่มหน่วยความจำหรือโอเวอร์เฮดของประสิทธิภาพ
หรือคุณสามารถใช้ประโยชน์จากความจริงที่ว่าCollections.sort()
(หรือArrays.sort()
) มีเสถียรภาพ (ไม่เรียงลำดับองค์ประกอบที่เท่ากัน) และใช้Comparator
เพื่อเรียงลำดับตามอายุก่อนแล้วค่อยเรียงลำดับชื่อ
ในกรณีเฉพาะนี้ไม่ได้เป็นความคิดที่ดีมาก แต่ถ้าคุณต้องสามารถเปลี่ยนลำดับการเรียงในขณะรันไทม์อาจเป็นประโยชน์
คุณสามารถใช้ตัวเปรียบเทียบอนุกรมทั่วไปเพื่อเรียงลำดับคอลเล็กชันตามหลายฟิลด์
import org.apache.commons.lang3.reflect.FieldUtils;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* @author MaheshRPM
*/
public class SerialComparator<T> implements Comparator<T> {
List<String> sortingFields;
public SerialComparator(List<String> sortingFields) {
this.sortingFields = sortingFields;
}
public SerialComparator(String... sortingFields) {
this.sortingFields = Arrays.asList(sortingFields);
}
@Override
public int compare(T o1, T o2) {
int result = 0;
try {
for (String sortingField : sortingFields) {
if (result == 0) {
Object value1 = FieldUtils.readField(o1, sortingField, true);
Object value2 = FieldUtils.readField(o2, sortingField, true);
if (value1 instanceof Comparable && value2 instanceof Comparable) {
Comparable comparable1 = (Comparable) value1;
Comparable comparable2 = (Comparable) value2;
result = comparable1.compareTo(comparable2);
} else {
throw new RuntimeException("Cannot compare non Comparable fields. " + value1.getClass()
.getName() + " must implement Comparable<" + value1.getClass().getName() + ">");
}
} else {
break;
}
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return result;
}
}
Arrays.sort(persons, new PersonComparator());
import java.util.Comparator;
public class PersonComparator implements Comparator<? extends Person> {
@Override
public int compare(Person o1, Person o2) {
if(null == o1 || null == o2 || null == o1.getName() || null== o2.getName() ){
throw new NullPointerException();
}else{
int nameComparisonResult = o1.getName().compareTo(o2.getName());
if(0 == nameComparisonResult){
return o1.getAge()-o2.getAge();
}else{
return nameComparisonResult;
}
}
}
}
class Person{
int age; String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
รุ่นที่ปรับปรุงแล้ว:
public class PersonComparator implements Comparator<? extends Person> {
@Override
public int compare(Person o1, Person o2) {
int nameComparisonResult = o1.getName().compareToIgnoreCase(o2.getName());
return 0 == nameComparisonResult?o1.getAge()-o2.getAge():nameComparisonResult;
}
}
สำหรับชั้นเรียนBook
เช่นนี้:
package books;
public class Book {
private Integer id;
private Integer number;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "book{" +
"id=" + id +
", number=" + number +
", name='" + name + '\'' + '\n' +
'}';
}
}
การเรียงลำดับคลาสหลักด้วยวัตถุจำลอง
package books;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
Book b = new Book();
Book c = new Book();
Book d = new Book();
Book e = new Book();
Book f = new Book();
Book g = new Book();
Book g1 = new Book();
Book g2 = new Book();
Book g3 = new Book();
Book g4 = new Book();
b.setId(1);
b.setNumber(12);
b.setName("gk");
c.setId(2);
c.setNumber(12);
c.setName("gk");
d.setId(2);
d.setNumber(13);
d.setName("maths");
e.setId(3);
e.setNumber(3);
e.setName("geometry");
f.setId(3);
f.setNumber(34);
b.setName("gk");
g.setId(3);
g.setNumber(11);
g.setName("gk");
g1.setId(3);
g1.setNumber(88);
g1.setName("gk");
g2.setId(3);
g2.setNumber(91);
g2.setName("gk");
g3.setId(3);
g3.setNumber(101);
g3.setName("gk");
g4.setId(3);
g4.setNumber(4);
g4.setName("gk");
List<Book> allBooks = new ArrayList<Book>();
allBooks.add(b);
allBooks.add(c);
allBooks.add(d);
allBooks.add(e);
allBooks.add(f);
allBooks.add(g);
allBooks.add(g1);
allBooks.add(g2);
allBooks.add(g3);
allBooks.add(g4);
System.out.println(allBooks.size());
Collections.sort(allBooks, new Comparator<Book>() {
@Override
public int compare(Book t, Book t1) {
int a = t.getId()- t1.getId();
if(a == 0){
int a1 = t.getNumber() - t1.getNumber();
return a1;
}
else
return a;
}
});
System.out.println(allBooks);
}
}
ฉันไม่แน่ใจว่ามันน่าเกลียดที่จะเขียนคู่ปรับในชั้นบุคคลในกรณีนี้หรือไม่ ทำเช่นนี้:
public class Person implements Comparable <Person> {
private String lastName;
private String firstName;
private int age;
public Person(String firstName, String lastName, int BirthDay) {
this.firstName = firstName;
this.lastName = lastName;
this.age = BirthDay;
}
public int getAge() {
return age;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@Override
public int compareTo(Person o) {
// default compareTo
}
@Override
public String toString() {
return firstName + " " + lastName + " " + age + "";
}
public static class firstNameComperator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.firstName.compareTo(o2.firstName);
}
}
public static class lastNameComperator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.lastName.compareTo(o2.lastName);
}
}
public static class ageComperator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.age - o2.age;
}
}
}
public class Test {
private static void print() {
ArrayList<Person> list = new ArrayList();
list.add(new Person("Diana", "Agron", 31));
list.add(new Person("Kay", "Panabaker", 27));
list.add(new Person("Lucy", "Hale", 28));
list.add(new Person("Ashley", "Benson", 28));
list.add(new Person("Megan", "Park", 31));
list.add(new Person("Lucas", "Till", 27));
list.add(new Person("Nicholas", "Hoult", 28));
list.add(new Person("Aly", "Michalka", 28));
list.add(new Person("Adam", "Brody", 38));
list.add(new Person("Chris", "Pine", 37));
Collections.sort(list, new Person.lastNameComperator());
Iterator<Person> it = list.iterator();
while(it.hasNext())
System.out.println(it.next().toString());
}
}
Comparator
เพื่อหลีกเลี่ยงการส่งสัญญาณเข้า