按特定的String值对String数组进行排序

时间:2016-12-28 18:49:44

标签: java arrays string sorting collections

我有一个项目,其主要功能是将.txt文件读入String数组,并按每行中的特定String值对其进行排序。我的.txt文件是一份员工名单,包括他们的姓名,薪水和经验。以下是我的示例清单:

  1. 姓名:Thomas Green |总薪水:10 000 |经验:30个月
  2. 姓名:Anna Lang |总薪水:6 000 |经验:12个月
  3. 姓名:Micheal Holse |总薪水:8 000 |经验:27个月
  4. 现在我想要的是在使用扫描仪将此列表更改为数组后,通过名字,工资值或经验值对此列表进行排序。我读过有关比较器的内容,但无法找到正确的例子。如你所见,这个程序要做的是跳过" Name:"值并按名字的字母顺序排序。或者跳过其他字符串并按最低工资值对列表进行排序。对于经验来说,它应该从最低到最高的几个月排序。

    这是我到目前为止所能做的:

    import java.io.File;
    import java.io.IOException;
    import java.util.*;
    
    public class SortList { 
        public static int loadInt() {
            Scanner s = new Scanner(System.in);
    
            if(!s.hasNextInt()) {
                s.next();
                s.nextLine();   
                return loadInt();
            }
            return s.nextInt();
        }
    
    
        public static void main (String[] args) throws IOException{
            //show the list
            String token1 = "";
            Scanner inFile1 = new Scanner (new File ("list.txt")).useDelimiter(",\\s*");
    
            List<String> temps = new ArrayList<String>();
    
            while(inFile1.hasNext()) {
                token1 = inFile1.next();
                temps.add(token1);
            }
            inFile1.close();
    
            String[] tempsArray = temps.toArray(new String[0]);         
            for(String s : tempsArray) {
                System.out.println(s);
            }
    
            //Sort the list
    
            System.out.println("How do you want to sort?" + "\n" + "1. By name" + "\n" + "2. By salary" + "\n" + "3. By experience");
            int b;
            b = loadInt();
            if (b == 1){
                ArrayList<String> namesList = new ArrayList<>();
    
                for(int i = 0; i<tempsArray.length; i++){
                    namesList.add(tempsArray[i]);
                }
    
                Collections.sort(namesList, (name1, name5) -> name1.split(" ")[1].compareTo(name5.split(" ")[1]));
    
                for(String name : namesList){
                    System.out.println(name);
                }
    
            }
            if (b == 2){
                ArrayList<String> salaryList = new ArrayList<>();
    
                for(int i = 0; i<tempsArray.length; i++){
                    salaryList.add(tempsArray[i]);
                }
    
                Collections.sort(salaryList, (salary1, salary2) -> salary1.split(" ")[10].compareTo(salary2.split(" ")[10]));
    
                for(String salary : salaryList){
                    System.out.println(salary);
                }
    
            }
            if (b == 3){
                ArrayList<String> experienceList = new ArrayList<>();
    
                for(int i = 0; i<tempsArray.length; i++){
                    experienceList.add(tempsArray[i]);
                }
    
                Collections.sort(experienceList, (experience1, experience2) -> experience1.split(" ")[14].compareTo(experience2.split(" ")[14]));
    
                for(String experience : experienceList){
                    System.out.println(experience);
                }
            }
        } 
    }       
    

    现在,当我输入一个整数值时,我的代码并没有对列表进行排序。我这样做的方式是否正确?我通过互联网找到了Collection的例子,但它并不适合我。

3 个答案:

答案 0 :(得分:4)

正确的做法是使用EmployeefirstNamelastNamesalary字段定义experience对象。然后,您可以定义多个Comparator<Employee>实例,这些实例支持您的不同排序选项。然后,您可以创建List<Employee>并调用Collections.sort(),它会根据Comparator定义的排序对元素进行排序。

这个类看起来像这样:

public class Employee {
  private final String firstName;
  private final String lastName;
  private final int salary;
  private final int experience;

  // constructor, getters
}

您的Comparator可能看起来像这样:

public class FirstNameComparator implements Comparator<Employee> {
  @Override
  public int compare(Employee e1, Employee e2) {
    return e1.getFirstName().compareTo(e2.getFirstName());
  }
}

或者在Java 8中,您可以使用方法引用,只需将Comparator.comparing(Employee::getFirstName)传递给Comparator的{​​{1}}参数。

然后,只需要读取文件并从每行中提取字段并从每个行构建Collections.sort()即可。如果您对该部分不确定,本网站上有许多问题讨论解析文本文件中的数据。

答案 1 :(得分:0)

你的算法的问题在于,当你从文件中读取时,Scanner对象正在一次读取所有内容,并且ArrayList temps只加载了1个元素。将token1 = inFile1.next();更改为token1 = inFile1.nextLine();,其他一切正常。

答案 2 :(得分:0)

进一步加强dimo414的建议。如上所述,您创建了一个包含员工相关部分的类。

该类可以有像

这样的构造函数
public Employee(String firstName, String lastName, int salary, int experienceInMonths)

然后您将创建像

这样的员工
List<Employee> employees = new ArrayList<>();
employees.add( new Employee ("Bilbo", "Beutlin", 5, 10) );

但是,当然,你的日期来自一个文件,你说它有像

这样的行
Name: Thomas Green | Gross salary: 10 000 | Experience: 30 months

所以,你知道的是:

  1. 您编写的代码逐行读取该文件。
  2. 您创建一个辅助方法,它接受一个这样的行...并返回该
  3. 的Employee对象

    像:

    public Employee createEmployeeFrom(String line) {
    

    在该方法中,您只需解析该字符串并提取相关信息。鉴于您的格式,您可以这样做:

    • 使用String.split(“\ |”)...应该将您的行切成三个子串
    • 然后,第一个子串将是“Name:Thomas Green”。在这里你将使用String.substring()来获取“:”之后的所有内容;给你“托马斯格林”。然后你可以假设最后一个空格之后的任何东西都是姓氏;以及任何以前的名字
    • 然后你对输入的部分做了类似的事情(使用Integer.valueOf()等方法将字符串数字转换为int)
    • 最后,你打电话`返回新员工(firstNameParsedFromInput,....

    事情是:你必须分开关注。一个问题是使用Employee类建模您的数据;另一个问题是解析一个字符串以检索构成Employee的元素。只有当所有运行良好时,然后才会开始查看Collections.sort()并编写自己的Comparator类。