从文件读取,标记化,使用compareTo()排序不起作用?

时间:2014-06-06 16:46:49

标签: java collections tokenize

我正在从文本文件中读取数据,使用split()进行标记,使用它来填充学生对象,将其保存在列表中并对其进行排序。(如果名称相同,则按年龄排序。如果年龄也相同,按照rollno排序)。

public class MyClass {
    public static void main(String[] args)
    {try{
        Scanner scr=new Scanner(new File("studentdetails"));
        String str1=scr.nextLine();

        String[] tokens1=str1.split(",");
        Student s1 = new Student(Integer.parseInt(tokens1[0]), tokens1[1], Integer.parseInt(tokens1[2]));

        String str2=scr.nextLine();
        String[] tokens2=str2.split(",");
        Student s2 = new Student(Integer.parseInt(tokens2[0]), tokens2[1], Integer.parseInt(tokens2[2]));

        String str3=scr.nextLine();
        String[] tokens3=str3.split(",");
        Student s3 = new Student(Integer.parseInt(tokens3[0]), tokens3[1], Integer.parseInt(tokens3[2]));

        List<Student> list=new ArrayList<Student>();
        list.add(s1);   list.add(s2);   list.add(s3);
        Collections.sort(list);
        System.out.println(list);
    }
    catch(Exception e){e.printStackTrace();}
    }
}

这是我的Student类,它实现了类似的接口。

public class Student implements Comparable<Student> {
    private int rollno;
    private String name;
    private int age;
    Student(int r, String n, int a){ rollno=r; name=n; age=a;}

    public String toString()
    {return rollno+" "+name+" "+age;}

    public int compareTo(Student s) {
        if(name != s.name)  return (name).compareTo(s.name);
        if(age != s.age)    return new Integer(age).compareTo(s.age);
                            return new Integer(rollno).compareTo(s.rollno);
        }
}

学生详情的内容如下:(第一栏是rollno,第三栏是年龄)

33,Zack,44
5,Anna,5
4,Zack,4

现在有趣的是,我的数据按名称排序,但如果名称相同,则不按年龄排序,滚动等等。

如果我手动填充列表,compareTo()会起作用。但是从文件读取,标记化和排序会产生错误。

花了一整天的时间调试。你们JAVA都在那里专业,你能帮我吗?

3 个答案:

答案 0 :(得分:2)

您使用其身份(==!=)而不是其值(equals())决定名称是否“相等”。

从文件读入时,

names.name不是同一个对象,即使它们具有相同的值。您的比较器应该检查它们的值。您之前没有注意到这一点,因为编译器会在源代码中实现文字字符串,因此如果您在源代码中编写两次相同的字符串,它将是同一个对象,{{1 }}和==似乎可行。

您的比较器看起来应该更像这样:

!=

答案 1 :(得分:0)

我通常会在这种情况下使用这种代码。

      public MyClass{
            private String names[];
            private int ages[];
            private int roll[];

            public void TextFileReader(){
            Scanner ob = null;
            try{
            ob = new Scanner(new FileReader("studentdetails"));
            int c = 0;
            while(ob.hasNext()){`
            String sp = ob.next();
            String arr[] = s.split("\\;");
            roll[c] = Integer.parseInt(arr[0]);
            name[c] = Integer.parseInt(arr[1]);
            age[c] = Integer.parseInt(arr[2]);
            c++;
}
            }
    catch(FileNotFoundExcpetion e){
    System.out.println("Error"+e.getMessage);
    }
            }


            public void sort(){
            for(int i = 0; i < names.lenght; i++){
                for(int c = i + 1; c < names.length; c++){
                 if(names[i].CompareTo(names[c]) > 0){
                    roll[i] = roll[i] + roll[c];
                    roll[c] = roll[i] - roll[c];
                    roll[i] = roll[i] - roll[c];
                    age[i] = age[i] + age[c];
                    age[c] = age[i] - age[c];
                    age[c] = age[i] - age[c];
                    String n = names[i];
                    names[i] = names[c];
                    names[c] = n;
    break;
    }
    if(age[i] > age[c] && name[i].compare(names[c]) == 0){
     roll[i] = roll[i] + roll[c];
                    roll[c] = roll[i] - roll[c];
                    roll[i] = roll[i] - roll[c];
                    age[i] = age[i] + age[c];
                    age[c] = age[i] - age[c];
                    age[c] = age[i] - age[c];
                    String n = names[i];
                    names[i] = names[c];
                    names[c] = n;
    break;
    }
    if(roll[i] > roll[c] && age[i] = age[c] && names[i].CompareTo(names[c]) == 0){
     roll[i] = roll[i] + roll[c];
                    roll[c] = roll[i] - roll[c];
                    roll[i] = roll[i] - roll[c];
                    age[i] = age[i] + age[c];
                    age[c] = age[i] - age[c];
                    age[c] = age[i] - age[c];
                    String n = names[i];
                    names[i] = names[c];
                    names[c] = n;

    }

        }
        }
        }


        public String[] getNames(){
        return names;
        }

        public int[] getRoll(){
        return roll;
        }

        public int[] getAge(){
        return age;
        }

        public int getCount(){
        return c;
        }

    public static void main(String args[]){
    MyClass ob = new MyClass();
    ob.TextFileReader();
    ob.sort();
    int count = ob.getCount();
    String x[] = ob.getNames();
    int y[] = ob.getAge();
    int z[] = ob.getRoll();
    for(int i = 0; i < c; i++){
    System.out.println(z[i]+","+x[i]+","+y[i]);
    }

        }

答案 2 :(得分:0)

除了名字之外,这绝不会比较:

格式正确,您可以看到您的问题:

这比较了名称和退货,它永远不会评估agerollno

public int compareTo(Student s) 
{
    if(name != s.name) 
    {
        return (name).compareTo(s.name);
    }
    if(age != s.age)
    {
        return new Integer(age).compareTo(s.age);
    }
    return new Integer(rollno).compareTo(s.rollno);
}

惯用解决方案:

对于这种特殊情况,这可能看起来过于复杂,但这个简单的案例是如何构建将使用适当的接口尽可能模块化的东西的一个很好的例子。

使用Comparator代替将所有逻辑直接放在Comparable中,可以让您在比较事物的顺序上获得更大的灵活性。

这是一个稻草人解决方案,因为我从不使用Comparable,除非它比较每个字段的相等性而不是像这样的多字段排序。

在此示例中,CompositeComparable将拥有compareTo所拥有的代码。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CompositeComparable
{
    public static void main(final String[] args)
    {
        final Student s1 = new Student(33, "Zack", 44);
        final Student s2 = new Student(5, "Anna", 5);
        final Student s3 = new Student(4, "Zack", 4);

        final List<Student> l = new ArrayList<Student>();
        l.add(s1);
        l.add(s2);
        l.add(s3);
        Collections.sort(l);
        for (final Student s : l)
        {
            System.out.println(s);
        }
    }

    public static class Student implements Comparable<Student>
    {
        private int rollno;
        private String name;
        private int age;

        public Student(int r, String n, int a)
        {
            rollno = r;
            name = n;
            age = a;
        }

        public String toString(){ return String.format("%d,%s,%d", rollno, name, age); }

        @Override
        public int compareTo(final Student o)
        {
            int result = new NameComparator().compare(this, o);
            if ( result != 0 ) { return result; }
            result = new AgeComparator().compare(this, o);
            if (result != 0) { return result; }
            result = new RollComparator().compare(this, o);
            if (result != 0) { return result; }
            return 0;
        }
    }

    public static class NameComparator implements Comparator<Student>
    {
        @Override
        public int compare(final Student o1, final Student o2)
        {
            return o1.name.compareTo(o2.name);
        }
    }

    public static class AgeComparator implements Comparator<Student>
    {
        @Override
        public int compare(final Student o1, final Student o2)
        {
            return Integer.compare(o1.age, o2.age);
        }
    }

    public static class RollComparator implements Comparator<Student>
    {
        @Override
        public int compare(final Student o1, final Student o2)
        {
            return Integer.compare(o1.rollno, o2.rollno);
        }
    }
}

输出:

5,Anna,5
4,Zack,4
33,Zack,44

奖金代码:

以下是通用CompositeComparator

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class CompositeComparator <T> implements Comparator<T>
{
    private List<Comparator<T>> comparators;

    public CompositeComparator(@Nonnull final Comparator<T>...comparators)
    {
        this.comparators = new ArrayList<Comparator<T>>(Arrays.asList(comparators));
    }

    @Override
    public int compare(final T o1, final T o2)
    {
        int result = 0;
        for (final Comparator<T> c : this.comparators)
        {
            result = c.compare(o1, o2);
            if (result != 0) { break; }
        }
        return result;
    }
}