根据 java 中的字段对自定义 Object class 进行多重排序
Multiple Sorting of an custom Object class by its field in java
package com.learnjava;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Stream;
public class EmployeeSortByGroup {
public static void sortEmployeeByGrp(List<Person> persons, String[] sortBy){
for(int i=0;i<sortBy.length;i++){
switch (sortBy.length) {
case 1:
if(sortBy !=null && sortBy[0].contains("firstname")){
Collections.sort(persons, Comparator.comparing(Person::getFirstName));
}
if(sortBy !=null && sortBy[0].contains("lastname")){
Collections.sort(persons, Comparator.comparing(Person::getLastName));
}
if(sortBy !=null && sortBy[0].contains("age")){
Collections.sort(persons, Comparator.comparingInt(Person::getAge));
}
if(sortBy !=null && sortBy[0].contains("country")){
Collections.sort(persons, Comparator.comparing(Person::getCountry));
}
break;
case 2:
if(sortBy !=null && sortBy[0].contains("firstname") && sortBy[1].contains("lastname")){
Collections.sort(persons, Comparator.comparing(Person::getFirstName).thenComparing(Person::getLastName));
}
if(sortBy !=null && sortBy[0].contains("firstname") && sortBy[1].contains("age")){
Collections.sort(persons, Comparator.comparing(Person::getFirstName).thenComparingInt(Person::getAge));
}
if(sortBy !=null && sortBy[0].contains("firstname") && sortBy[1].contains("country")){
Collections.sort(persons, Comparator.comparing(Person::getFirstName).thenComparing(Person::getCountry));
}
break;
case 3:
//
case 4:
//
default:
break;
}
}
}
public static void main(String[] args) {
try {
Scanner sc=new Scanner(System.in);
System.out.println("Enter number of rows : ");
int rows=sc.nextInt();
System.out.println("Enter sort by:");
String sortByString=sc.next();
String[] sortByStringArr=sortByString.split("\;");
Stream<String> lines = Files.lines(
Paths.get("path to text file containing record")).skip(1).limit(rows);
long lineCount = Files.lines(Paths.get("path to the text file containing record")).skip(1).limit(rows).count();
Person[] persons = new Person[(int) lineCount];
String[] stringArray = lines.toArray(String[]::new);
for (int i=0;i<lineCount;i++){
persons[i]=new Person();
String[] perArr= stringArray[i].split("\|");
for (int j=0;j<perArr.length;j++){
persons[i].setFirstName((perArr[0]));
persons[i].setLastName((perArr[1]));
persons[i].setAge(Integer.parseInt(perArr[2]));
persons[i].setCountry((perArr[3]));
}
}
List<Person> t_arraylist = Arrays.asList(persons);
sortEmployeeByGrp(t_arraylist,sortByStringArr);
Stream.of(persons).forEach(s->System.out.println(s));
} catch (IOException e) {
e.printStackTrace();
}
}
}
//Person class
package com.learnjava;
import java.util.Comparator;
public class Person {
String FirstName;
String LastName;
int age;
String country;
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString() {
return ""+FirstName+"|"+LastName+"|"+age+"|"+country+"";
}
public Person() {
super();
}
public Person(String firstName, String lastName, int age, String country) {
super();
FirstName = firstName;
LastName = lastName;
this.age = age;
this.country = country;
}
}
###这种方法的任何更好的解决方案。如果用户输入的行计数为 5,排序方式为 "firstname;age",那么它将对文件中的 5 行进行排序,不包括 header 的第一行,并先按名字排序,然后按年龄排序。更好的方法来处理所有这些用户输入的排序排列。
建立化合物Comparator
incrementally using thenComparing(Comparator)
。
public static Comparator<Person> parseSortBy(String sortBy) {
Comparator<Person> sortComparator = null;
for (String field : sortBy.split(";")) {
Comparator<Person> c;
switch (field) {
case "firstname":
c = Comparator.comparing(Person::getFirstName);
break;
case "lastname":
c = Comparator.comparing(Person::getLastName);
break;
case "age":
c = Comparator.comparingInt(Person::getAge);
break;
case "country":
c = Comparator.comparing(Person::getCountry);
break;
default:
throw new IllegalArgumentException("Unknown sort spec: " + field);
}
sortComparator = (sortComparator == null ? c : sortComparator.thenComparing(c));
}
return sortComparator;
}
虽然我实际上会稍微改变一下,让方法只构建 Comparator
,让调用者使用它。
我还会使该方法的一般部分可重用。
public static Comparator<Person> parsePersonSortBy(String sortBy) {
return parseSortBy(sortBy, field -> {
switch (field) {
case "firstname": return Comparator.comparing(Person::getFirstName);
case "lastname": return Comparator.comparing(Person::getLastName);
case "age": return Comparator.comparingInt(Person::getAge);
case "country": return Comparator.comparing(Person::getCountry);
default: throw new IllegalArgumentException("Unknown sort spec: " + field);
}
});
}
// The following method should be in a separate helper class for reusability
public static <E> Comparator<E> parseSortBy(String sortBy, Function<String, Comparator<E>> fieldComparatorMapper) {
Comparator<E> sortComparator = null;
for (String field : sortBy.split(";")) {
Comparator<E> c = fieldComparatorMapper.apply(field);
sortComparator = (sortComparator == null ? c : sortComparator.thenComparing(c));
}
return sortComparator;
}
// You will now use it like this. No need for using a List
Arrays.sort(persons, parsePersonSortBy(sortByString));
您现在可以轻松地增强解析以支持 降序 排序,例如通过在字段名称后添加一个 -
减号,这样 "firstname-;age"
将按 firstname
降序排序,然后按 age
升序排序。
public static <E> Comparator<E> parseSortBy(String sortBy, Function<String, Comparator<E>> fieldComparatorMapper) {
Comparator<E> sortComparator = null;
for (String field : sortBy.split(";")) {
boolean descending = field.endsWith("-");
Comparator<E> c = fieldComparatorMapper.apply(descending ? field.substring(0, field.length() - 1) : field);
if (descending)
c = c.reversed();
sortComparator = (sortComparator == null ? c : sortComparator.thenComparing(c));
}
return sortComparator;
}
package com.learnjava;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Stream;
public class EmployeeSortByGroup {
public static void sortEmployeeByGrp(List<Person> persons, String[] sortBy){
for(int i=0;i<sortBy.length;i++){
switch (sortBy.length) {
case 1:
if(sortBy !=null && sortBy[0].contains("firstname")){
Collections.sort(persons, Comparator.comparing(Person::getFirstName));
}
if(sortBy !=null && sortBy[0].contains("lastname")){
Collections.sort(persons, Comparator.comparing(Person::getLastName));
}
if(sortBy !=null && sortBy[0].contains("age")){
Collections.sort(persons, Comparator.comparingInt(Person::getAge));
}
if(sortBy !=null && sortBy[0].contains("country")){
Collections.sort(persons, Comparator.comparing(Person::getCountry));
}
break;
case 2:
if(sortBy !=null && sortBy[0].contains("firstname") && sortBy[1].contains("lastname")){
Collections.sort(persons, Comparator.comparing(Person::getFirstName).thenComparing(Person::getLastName));
}
if(sortBy !=null && sortBy[0].contains("firstname") && sortBy[1].contains("age")){
Collections.sort(persons, Comparator.comparing(Person::getFirstName).thenComparingInt(Person::getAge));
}
if(sortBy !=null && sortBy[0].contains("firstname") && sortBy[1].contains("country")){
Collections.sort(persons, Comparator.comparing(Person::getFirstName).thenComparing(Person::getCountry));
}
break;
case 3:
//
case 4:
//
default:
break;
}
}
}
public static void main(String[] args) {
try {
Scanner sc=new Scanner(System.in);
System.out.println("Enter number of rows : ");
int rows=sc.nextInt();
System.out.println("Enter sort by:");
String sortByString=sc.next();
String[] sortByStringArr=sortByString.split("\;");
Stream<String> lines = Files.lines(
Paths.get("path to text file containing record")).skip(1).limit(rows);
long lineCount = Files.lines(Paths.get("path to the text file containing record")).skip(1).limit(rows).count();
Person[] persons = new Person[(int) lineCount];
String[] stringArray = lines.toArray(String[]::new);
for (int i=0;i<lineCount;i++){
persons[i]=new Person();
String[] perArr= stringArray[i].split("\|");
for (int j=0;j<perArr.length;j++){
persons[i].setFirstName((perArr[0]));
persons[i].setLastName((perArr[1]));
persons[i].setAge(Integer.parseInt(perArr[2]));
persons[i].setCountry((perArr[3]));
}
}
List<Person> t_arraylist = Arrays.asList(persons);
sortEmployeeByGrp(t_arraylist,sortByStringArr);
Stream.of(persons).forEach(s->System.out.println(s));
} catch (IOException e) {
e.printStackTrace();
}
}
}
//Person class
package com.learnjava;
import java.util.Comparator;
public class Person {
String FirstName;
String LastName;
int age;
String country;
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString() {
return ""+FirstName+"|"+LastName+"|"+age+"|"+country+"";
}
public Person() {
super();
}
public Person(String firstName, String lastName, int age, String country) {
super();
FirstName = firstName;
LastName = lastName;
this.age = age;
this.country = country;
}
}
###这种方法的任何更好的解决方案。如果用户输入的行计数为 5,排序方式为 "firstname;age",那么它将对文件中的 5 行进行排序,不包括 header 的第一行,并先按名字排序,然后按年龄排序。更好的方法来处理所有这些用户输入的排序排列。
建立化合物Comparator
incrementally using thenComparing(Comparator)
。
public static Comparator<Person> parseSortBy(String sortBy) {
Comparator<Person> sortComparator = null;
for (String field : sortBy.split(";")) {
Comparator<Person> c;
switch (field) {
case "firstname":
c = Comparator.comparing(Person::getFirstName);
break;
case "lastname":
c = Comparator.comparing(Person::getLastName);
break;
case "age":
c = Comparator.comparingInt(Person::getAge);
break;
case "country":
c = Comparator.comparing(Person::getCountry);
break;
default:
throw new IllegalArgumentException("Unknown sort spec: " + field);
}
sortComparator = (sortComparator == null ? c : sortComparator.thenComparing(c));
}
return sortComparator;
}
虽然我实际上会稍微改变一下,让方法只构建 Comparator
,让调用者使用它。
我还会使该方法的一般部分可重用。
public static Comparator<Person> parsePersonSortBy(String sortBy) {
return parseSortBy(sortBy, field -> {
switch (field) {
case "firstname": return Comparator.comparing(Person::getFirstName);
case "lastname": return Comparator.comparing(Person::getLastName);
case "age": return Comparator.comparingInt(Person::getAge);
case "country": return Comparator.comparing(Person::getCountry);
default: throw new IllegalArgumentException("Unknown sort spec: " + field);
}
});
}
// The following method should be in a separate helper class for reusability
public static <E> Comparator<E> parseSortBy(String sortBy, Function<String, Comparator<E>> fieldComparatorMapper) {
Comparator<E> sortComparator = null;
for (String field : sortBy.split(";")) {
Comparator<E> c = fieldComparatorMapper.apply(field);
sortComparator = (sortComparator == null ? c : sortComparator.thenComparing(c));
}
return sortComparator;
}
// You will now use it like this. No need for using a List
Arrays.sort(persons, parsePersonSortBy(sortByString));
您现在可以轻松地增强解析以支持 降序 排序,例如通过在字段名称后添加一个 -
减号,这样 "firstname-;age"
将按 firstname
降序排序,然后按 age
升序排序。
public static <E> Comparator<E> parseSortBy(String sortBy, Function<String, Comparator<E>> fieldComparatorMapper) {
Comparator<E> sortComparator = null;
for (String field : sortBy.split(";")) {
boolean descending = field.endsWith("-");
Comparator<E> c = fieldComparatorMapper.apply(descending ? field.substring(0, field.length() - 1) : field);
if (descending)
c = c.reversed();
sortComparator = (sortComparator == null ? c : sortComparator.thenComparing(c));
}
return sortComparator;
}