Java 按特定字符串值对字符串数组排序

Java 按特定字符串值对字符串数组排序,java,arrays,string,sorting,collections,Java,Arrays,String,Sorting,Collections,我有一个项目,其主要功能是将.txt文件读入字符串数组,并按每行中的特定字符串值对其进行排序。我的.txt文件是一份员工名单,上面有他们的姓名、工资和经验。下面是我的示例列表: 姓名:托马斯·格林|工资总额:10000 |工作经验:30个月 姓名:Anna Lang |工资总额:6000 |工作经验:12个月 姓名:Micheal Holse |工资总额:8000 |工作经验:27个月 现在我要做的是,在使用扫描器将列表更改为数组后,通过名字、薪水值或经验值对列表进行排序。我读过关于Compar

我有一个项目,其主要功能是将.txt文件读入字符串数组,并按每行中的特定字符串值对其进行排序。我的.txt文件是一份员工名单,上面有他们的姓名、工资和经验。下面是我的示例列表:

姓名:托马斯·格林|工资总额:10000 |工作经验:30个月 姓名:Anna Lang |工资总额:6000 |工作经验:12个月 姓名:Micheal Holse |工资总额:8000 |工作经验:27个月 现在我要做的是,在使用扫描器将列表更改为数组后,通过名字、薪水值或经验值对列表进行排序。我读过关于Comparator的文章,但找不到正确的例子。正如您所看到的,这个程序要做的是跳过Name:value并按名字的字母顺序对其排序。或者跳过其他字符串并按最低薪资值对列表进行排序。经验也是一样,它应该按月数从最低到最高排序

以下是到目前为止我能做的:

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);
            }
        }
    } 
}       

目前,当我输入整数值时,我的代码不会对列表进行排序。我这样做对吗?我通过internet找到了一个收集示例,但它对我不起作用。

正确的做法是使用firstName、lastName、salary和experience字段定义一个Employee对象。然后,您可以定义多个支持不同排序选项的比较器实例。然后您可以创建一个列表和调用,它将根据比较器定义的顺序对元素进行排序

该类可能如下所示:

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

  // constructor, getters
}
public class FirstNameComparator implements Comparator<Employee> {
  @Override
  public int compare(Employee e1, Employee e2) {
    return e1.getFirstName().compareTo(e2.getFirstName());
  }
}
您的比较器可能如下所示:

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

  // constructor, getters
}
public class FirstNameComparator implements Comparator<Employee> {
  @Override
  public int compare(Employee e1, Employee e2) {
    return e1.getFirstName().compareTo(e2.getFirstName());
  }
}
或者在Java8中,您可以使用方法引用,只需将Comparator.comparingEmployee::getFirstName传递给Collections.sort的Comparator参数


然后,只需读取文件并从每行中提取字段,然后从每行中构造一个雇员。如果您对文本文件中的数据不确定,本网站上会有许多问题讨论如何解析这些数据。

正确的做法是使用firstName、lastName、salary和experience字段定义员工对象。然后,您可以定义多个支持不同排序选项的比较器实例。然后您可以创建一个列表和调用,它将根据比较器定义的顺序对元素进行排序

该类可能如下所示:

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

  // constructor, getters
}
public class FirstNameComparator implements Comparator<Employee> {
  @Override
  public int compare(Employee e1, Employee e2) {
    return e1.getFirstName().compareTo(e2.getFirstName());
  }
}
您的比较器可能如下所示:

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

  // constructor, getters
}
public class FirstNameComparator implements Comparator<Employee> {
  @Override
  public int compare(Employee e1, Employee e2) {
    return e1.getFirstName().compareTo(e2.getFirstName());
  }
}
或者在Java8中,您可以使用方法引用,只需将Comparator.comparingEmployee::getFirstName传递给Collections.sort的Comparator参数


然后,只需读取文件并从每行中提取字段,然后从每行中构造一个雇员。如果您对文本文件中的数据不确定,本网站上会有很多问题讨论解析文本文件中的数据。

算法的问题是,当您从文件中读取数据时,Scanner对象会立即读取所有内容,而ArrayList temps只加载了1个元素。更改令牌1=inFile1.next;token1=infie1.nextLine;,其他一切正常。

算法的问题是,当您从文件中读取时,Scanner对象会立即读取所有内容,而ArrayList temps只加载了1个元素。更改令牌1=inFile1.next;token1=infie1.nextLine;,其他一切正常。

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

该类可以有一个类似

public Employee(String firstName, String lastName, int salary, int experienceInMonths)
然后你会创造出像这样的员工

List<Employee> employees = new ArrayList<>();
employees.add( new Employee ("Bilbo", "Beutlin", 5, 10) );
那么,你知道的是:

您可以编写代码逐行读取该文件 您创建了一个助手方法,该方法接受一条这样的线。。。并为其返回一个Employee对象 比如:

在该方法中,您只需解析该字符串并提取相关信息。根据您的格式,您可以执行以下操作:

使用\|。。。这应该把你的行切成三个子串 第一个子串是Name:thomasgreen。在这里,您将使用String.substring获取以下内容:;给你托马斯·格林。然后你可以假设最后一个空格后面的任何东西都是姓氏;而之前的任何东西都是第一个名字 然后使用Integer.valueOf等方法对输入部分执行类似操作,以将字符串数字转换为int 最后,调用“returnnewEmployeeFirstNameParsedFromInput,…”。。。。
事情是:你必须分开考虑。一个问题是使用Employee类对数据建模;另一个问题是解析字符串以检索构成员工的元素。只有当所有这些都很好地工作时,您才开始研究Collections.sort并编写自己的Comparator类。

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

那个班可以有一个c 结构式

public Employee(String firstName, String lastName, int salary, int experienceInMonths)
然后你会创造出像这样的员工

List<Employee> employees = new ArrayList<>();
employees.add( new Employee ("Bilbo", "Beutlin", 5, 10) );
那么,你知道的是:

您可以编写代码逐行读取该文件 您创建了一个助手方法,该方法接受一条这样的线。。。并为其返回一个Employee对象 比如:

在该方法中,您只需解析该字符串并提取相关信息。根据您的格式,您可以执行以下操作:

使用\|。。。这应该把你的行切成三个子串 第一个子串是Name:thomasgreen。在这里,您将使用String.substring获取以下内容:;给你托马斯·格林。然后你可以假设最后一个空格后面的任何东西都是姓氏;而之前的任何东西都是第一个名字 然后使用Integer.valueOf等方法对输入部分执行类似操作,以将字符串数字转换为int 最后,调用“returnnewEmployeeFirstNameParsedFromInput,…”。。。。

事情是:你必须分开考虑。一个问题是使用Employee类对数据建模;另一个问题是解析字符串以检索构成员工的元素。只有当所有这些都很好地工作时,您才开始研究Collections.sort并编写自己的Comparator类。

这里真正的问题是,在处理各种排序操作之前,您需要一个合理的对象模型。从这个意义上说,迪莫的答案绝对是你必须要了解的。谢谢你的解释。但如果我创建名为Employee的对象,我将如何从txt文件加载列表?我是Java初学者,因此我无法想象如何从txt文件加载对象。哇,我花了一些时间为您写了一个答案。希望这会有所帮助,因为我有一种模糊的感觉,我甚至不会看到太多的赞成票…这里真正的事情是,你需要一个合理的对象模型,然后再做任何关于这些排序的事情。从这个意义上说,迪莫的答案绝对是你必须要了解的。谢谢你的解释。但如果我创建名为Employee的对象,我将如何从txt文件加载列表?我是Java初学者,因此我无法想象如何从txt文件加载对象。哇,我花了一些时间为您写了一个答案。希望这会有所帮助,因为我有一种模糊的感觉,我甚至不会看到太多的赞成票…+1,因为我提到了带有Comparator.comparating的Java8解决方案。大多数人甚至不知道从哪里开始实现Comparator,所以一个现成的解决方案是非常有用的。感谢您的解释,但是我应该用构造函数创建一个文件,还是在我的程序中实现这一部分。所以最好的选择是将数据解析成可比较的字段?恐怕我不理解你的问题。类有构造函数,而不是文件;您可以在任何地方定义比较器—单独的文件、SortList中的嵌套类,甚至是匿名类/lambda。关键点是将解析步骤与排序步骤分开。将文本文件解析为结构化对象,然后对这些对象进行排序。@ifly6是的,Java 8对Comparator进行了一些重大改进。在Java-8之前的版本中,Guava的和类也有类似的用途。+1用于使用Comparator.Comparating提及Java 8解决方案。大多数人甚至不知道从哪里开始实现Comparator,所以一个现成的解决方案是非常有用的。感谢您的解释,但是我应该用构造函数创建一个文件,还是在我的程序中实现这一部分。所以最好的选择是将数据解析成可比较的字段?恐怕我不理解你的问题。类有构造函数,而不是文件;您可以在任何地方定义比较器—单独的文件、SortList中的嵌套类,甚至是匿名类/lambda。关键点是将解析步骤与排序步骤分开。将文本文件解析为结构化对象,然后对这些对象进行排序。@ifly6是的,Java 8对Comparator进行了一些重大改进。在Java-8土地GuAVA和类中有类似的用途。感谢输入,我将在编写Effice类时考虑这种方法。欢迎您。请记住我的回答,一旦你达到15个代表和投票特权:谢谢你的投入,我会考虑这个方法时写的雇员类。当您达到15个代表和投票特权时,请记住我的回答:-