【问题标题】:Copying contents of file into array of linked list and sort it将文件内容复制到链表数组中并对其进行排序
【发布时间】:2013-01-28 11:33:42
【问题描述】:

我有一个逗号分隔的文件,其中包含 员工姓名、公司、年份。

一名员工可能隶属于多家公司。

例如,

约翰,谷歌,2
约翰,微软,1
詹姆斯,特斯拉,1
詹姆斯,苹果,5

我已使用 java 扫描仪检索到信息

scanner.useDelimiter(",|\\n");
    while (scanner.hasNext()) {
        String line = scanner.next()

我是 Java 新手,我正在尝试使用链表数组或数组数组以排序顺序(使用经验作为排序标准)插入上述内容。所以

employee -> Company1 -> Company2....(按员工经验排序)

所以在上面的例子中,它会是:

约翰->微软->谷歌
詹姆斯->特斯拉->苹果

有人能指出正确的方向吗?

注意:如果经验相同,那么哪个公司先来并不重要。

【问题讨论】:

  • 您提供的示例中存在矛盾,因为John 您按升序排序,而James 则相反!?
  • 编辑了我的问题 iTech。我对java有点陌生..我不明白可比性
  • 您是否关心实际人员的顺序,而不是该人工作过的公司?

标签: java arrays oop sorting linked-list


【解决方案1】:

为 Person 使用这个类

公共类人{

@Getter @Setter
private String name;

@Getter @Setter
private TreeMap<String, String> companyExperience;

public Person(){
    companyExperience = new TreeMap<String, String>();
}

}

在 TreeMap 中使用体验作为键将自动按升序对 Person 的公司进行排序。

你的主类应该是这样的

public class App 
{
    public static void main( String[] args )
    {
        HashMap<String, Person> persons = new HashMap<String, Person>();

        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("C:\\Users\\Public Administrator\\test.txt"));
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String line = null;

        try {
            while ((line = br.readLine()) != null) {
                String[] fields = line.split(",");
                String personName = fields[0];
                Person existingPerson = persons.get(personName);
                if (existingPerson==null){
                    Person newPerson = new Person();
                    newPerson.setName(personName);
                    newPerson.getCompanyExperience().put(Integer.parseInt(fields[2])+fields[1], fields[1]);
                    persons.put(personName, newPerson);
                } else{
                    existingPerson.getCompanyExperience().put(Integer.parseInt(fields[2])+fields[1], fields[1]);
                }
             }
        } catch (NumberFormatException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }    

        //output
        Iterator<Map.Entry<String, Person>> entries = persons.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<String, Person> entry = entries.next();
            Person _person = entry.getValue();
            System.out.print(_person.getName());

            Iterator<Map.Entry<String, String>> companyExperiences = _person.getCompanyExperience().entrySet().iterator();
            while (companyExperiences.hasNext()) {
                Map.Entry<String, String> companyExperience = companyExperiences.next();

                System.out.print(" > "+companyExperience.getValue());
            }
            System.out.println();

        }
    }
}

我已经测试过了,它看起来很漂亮,对我来说很好。

顺便说一下,@Getter 和@Setter 注解来自 Lombok 项目。您可以使用它,也可以创建自己的 getter/setter。

【讨论】:

  • @Micheal 除非我遗漏了什么,否则此解决方案将无法处理同一个人拥有两个相同长度的工作的情况,例如:James,Google,1 James,Apple,1 试一试.
  • @sharakan 你是对的。我已经通过使用体验+公司(现在是字符串)作为 TreeMap 的键来修复它。现在它适用于所有情况。好点。
  • 现在你有一个类似的问题,当你在同一家公司工作了两次相同的时间。你真的不想要Set,因为项目不应该被认为是唯一的。
【解决方案2】:

使用readLine() 读取您的文件并使用 split 获取数据的每个字段,例如:

BufferedReader br = new BufferedReader(new FileReader("FileName"));
String line = null;
ArrayList<Person> list = new ArrayList<Person>();

while ((line = br.readLine()) != null) {
    String[] fields = line.split(",");
    list.add(new Person(fields[0], fields[1], Integer.parseInt(fields[2])));
 } 

然后,您可以将数据保存在采用自定义类的 ArrayList 中,例如Person 存储此人的信息并在您执行排序逻辑的地方实现 Comparable

如果您需要按人名对数据进行分组,您可以考虑使用Hashtable,其中键是人名,值是经验的ArrayList

你可以为你的数据定义一个类,例如

class Person implements Comparable<Person> {
    private String name;
    private String company;
    private int experience;

    public Person(String name, String company, int experience) {

        this.name = name;
        this.company = company;
        this.experience = experience;
    }

    public int getExperience() {
        return experience;
    }

    @Override
    public int compareTo(Person person) {
        return new Integer(experience).compareTo(person.getExperience());
    }
}

对您的列表进行排序只需调用Collections.sort(list);;但是此列表将包含所有数据,因此请修改代码以按员工姓名对数据进行分组,并为每个员工提供一个列表

【讨论】:

  • -1 这并没有给出 OP 想要的结果。由于文件中的每行都有一个 Person 对象,因此每个人名都有两个对象,因此排序可以拆分同一个人。例如:您的排序列表将包含类似 John:Microsoft:1, James:Tesla:1, John:Google:2, James:Apple:5 的内容
  • 正确,我错过了,只需阅读代码!我的错。您是否将进入他的 Emp->Comp1->Comp2 结构的最后一步作为练习留给读者?
  • Can someone point me to the right direction? 这是问题所在,我建议的解决方案很明确。其实你对这个问题的回答有一个严重的缺陷,但是我没有时间评论它
【解决方案3】:

出于您的目的,听起来您确实想要一个对象来代表一个具有一定经验的人。由于您的输入源对数据进行了非规范化,因此最简单的方法是在解析文件时填充 Map&lt;String,Person&gt;

scanner.useDelimiter(",|\\n");
while (scanner.hasNext()) {
    String line = scanner.next();
    String[] fields = line.split(",");

    String name = fields[0];
    Person person = map.get(name);
    if (person == null) {
        person = new Person(name);
        map.put(name, person);
    }
    person.addJob(fields[1], Integer.parseInt(fields[2]));
}

List<Person> people = new ArrayList<Person>(map.values());

在此过程之后,您最终会得到一份人员列表,没有特定的顺序。对于每个人,由于您希望按经验对他们的工作进行排序,因此您需要以使其保持有序的方式实现Person.addJobSortedSet 是一种非常好的方法,但是您不能插入重复项,并且由于您想按经验排序,并且一个人可能在两份工作中花费相同的时间需要使用替代方法。有几种方法可以做到这一点,但在不对您的数据做出假设的情况下,我建议保留 ListJob 对象的排序:

class Person {
    private final List<Job> jobs = new LinkedList<Job>();

    // Constructor, etc... 

    public void addJob(String companyName, int yearsOfExperience) {
        Job newJob = new Job(companyName, yearsOfExperience);
        int insertionIndex = Collections.binarySearch(jobs, newJob);
        if (insertionIndex < 0) {
            insertionIndex = (-(insertionIndex) - 1);
        }
        jobs.add(insertionIndex, newJob);
    }
}

最后,Job 应该实现Comparable&lt;Job&gt;,这样你就可以查找它:

class Job implements Comparable<Job> {
    private final String companyName;
    private final int yearsOfExperience;

    // Constructor, etc... 

    public int compareTo(Job otherJob) {
        return Integer.compare(yearsOfExperience,otherJob.yearsOfExperience);
    }
}

Person.addJob 中的那一点诡计将使 List 始终按 Job 的 'natural order' 排序。 (见Collections.binarySearch)。

【讨论】:

  • @ITech 你提到这个解决方案有一个“严重缺陷”。希望您有时间向我指出。
猜你喜欢
  • 2020-02-04
  • 2017-04-29
  • 1970-01-01
  • 2018-11-01
  • 2012-10-24
  • 1970-01-01
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多