Java 使用compareTo()读取文件、标记化和排序不会';不行?

Java 使用compareTo()读取文件、标记化和排序不会';不行?,java,collections,tokenize,Java,Collections,Tokenize,我从文本文件中读取数据,使用split()标记,使用它填充学生对象,将其保存在列表中并对其排序。(如果名称相同,则按年龄排序。如果年龄相同,则按rollno排序) 有趣的是,我的数据是按照名字排序的,但如果名字相同,它就不会按照年龄、rollno等进行排序 如果我手动填充列表,则compareTo()可以工作。然而,从文件读取、标记化和排序会产生错误 花了一整天的时间调试。所有的JAVA专家,你能帮我吗?你是在用名称的标识(==,!=)而不是它们的值(equals())来决定名称是否“相等” 从

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

有趣的是,我的数据是按照名字排序的,但如果名字相同,它就不会按照年龄、rollno等进行排序

如果我手动填充列表,则compareTo()可以工作。然而,从文件读取、标记化和排序会产生错误


花了一整天的时间调试。所有的JAVA专家,你能帮我吗?

你是在用名称的标识(
==
!=
)而不是它们的值(
equals()
)来决定名称是否“相等”

从文件读入时,
name
s.name
不是同一对象,即使它们具有相同的值。您的比较器应该检查它们的值。您以前没有注意到这一点,因为编译器将在源代码中插入文本字符串,因此如果在源代码中编写两次相同的字符串,它将是相同的对象,并且
==
=将显示为有效

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

// first compare by name. If different, return that immediately.
final int nameDiff = name.compareTo(s.name);
if (nameDiff != 0) return nameDiff;

// name is the same. Now compare age and return if different.
final int ageDiff = age - s.age;
if (ageDiff != 0) return ageDiff;

// final layer of sorting: rollno
return rollno - s.rollno;

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

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

        }
公共MyClass{
私有字符串名称[];
私人整数[];
私人整数滚动[];
public void TextFileReader(){
扫描器ob=null;
试一试{
ob=新扫描仪(新文件阅读器(“studentdetails”);
int c=0;
while(ob.hasNext()){`
字符串sp=ob.next();
字符串arr[]=s.split(“\\;”);
roll[c]=Integer.parseInt(arr[0]);
name[c]=Integer.parseInt(arr[1]);
年龄[c]=整数.parseInt(arr[2]);
C++;
}
}
捕获(FileNotFoundExcpetion e){
System.out.println(“错误”+e.getMessage);
}
}
公共无效排序(){
对于(int i=0;i0){
滚转[i]=滚转[i]+滚转[c];
卷[c]=卷[i]-卷[c];
卷[i]=卷[i]-卷[c];
年龄[i]=年龄[i]+年龄[c];
年龄[c]=年龄[i]-年龄[c];
年龄[c]=年龄[i]-年龄[c];
字符串n=名称[i];
名称[i]=名称[c];
名称[c]=n;
打破
}
if(age[i]>age[c]&&name[i]。比较(name[c])==0{
滚转[i]=滚转[i]+滚转[c];
卷[c]=卷[i]-卷[c];
卷[i]=卷[i]-卷[c];
年龄[i]=年龄[i]+年龄[c];
年龄[c]=年龄[i]-年龄[c];
年龄[c]=年龄[i]-年龄[c];
字符串n=名称[i];
名称[i]=名称[c];
名称[c]=n;
打破
}
如果(滚动[i]>滚动[c]&年龄[i]=年龄[c]&姓名[i]。比较(姓名[c])==0{
滚转[i]=滚转[i]+滚转[c];
卷[c]=卷[i]-卷[c];
卷[i]=卷[i]-卷[c];
年龄[i]=年龄[i]+年龄[c];
年龄[c]=年龄[i]-年龄[c];
年龄[c]=年龄[i]-年龄[c];
字符串n=名称[i];
名称[i]=名称[c];
名称[c]=n;
}
}
}
}
公共字符串[]getNames(){
返回姓名;
}
公共int[]getRoll(){
回程辊;
}
公共int[]getAge(){
回归年龄;
}
public int getCount(){
返回c;
}
公共静态void main(字符串参数[]){
MyClass ob=新的MyClass();
ob.TextFileReader();
ob.sort();
int count=ob.getCount();
字符串x[]=ob.getNames();
int y[]=ob.getAge();
int z[]=ob.getRoll();
对于(int i=0;i
除了名称之外,这将永远不会在任何东西上进行比较: 如果格式正确,您可以看到您的问题:

这将比较名称和返回值,它永远不会计算
age
rollno

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
中,可以让您更灵活地按顺序进行比较

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

在本例中,
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);
        }
    }
}
奖金代码: 这是一个通用的
复合比较程序

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;
    }
}
import javax.annotation.Nonnull;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Comparator;
导入java.util.List;
公共类CompositeComparator实现了Comparator
{
私人名单比较国;
公共复合比较程序(@Nonnull final Comparator…comparators)
{
this.comparators=newarraylist(Arrays.asList(comparators));
}
@凌驾
公共整数比较(最终tO1,最终tO2)
{
int结果=0;
for(最终比较器c:这个比较器)
{
结果=c.比较(o1,o2);
如果(结果!=0){break;}
}
返回结果;
}
}

通常compareTo根据比较结果返回0、-1或1。这并不重要,但当名为“a”的学生与“B”相比得到-1时,这有点奇怪,但如果有
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);
}
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
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;
    }
}