Многократная сортировка пользовательского класса объекта по его полю в java - PullRequest
0 голосов
/ 23 января 2020
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, а sortBy как «firstname; age», то она будет сортировать 5 строк из файла, исключая первую строку для заголовка и сортировку сначала по имени, а затем по возрасту. Лучший подход для обработки всех этих перестановок сортировки, которые вводит пользователь.

1 Ответ

0 голосов
/ 23 января 2020

Построить соединение Comparator постепенно , используя 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;
}
...