有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

树集合中的java,基于不同属性的自定义对象的排序和唯一性

下面是我的学生班

class Student implements Comparable {
   String name;
   int rollNo;

   @Override
   public int compareTo(Object obj) {
        return ((Student)obj).name.compareTo(this.name);
   }
} 

最新修改:但仍然没有得到正确的结果

@Override
public int compareTo(Object obj) {
    Student s = (Student) obj;
    if (name.equals(s.name)) { // achieving uniqueness
        return 0;
    } else {
        if (rollNo < s.rollNo) {
            return -1;
        } else if (rollNo > s.rollNo) {
            return 1;
        } else {
            // this makes `name` the second ordering option.
            // names don't equal here
            return name.compareTo(s.name);
        }
    }
}

如果我创建树集的对象<;学生>;,我得到了基于唯一名称的学生对象排序列表&;也按姓名排序

但我需要在我的树集合中使用唯一的学生名称<;学生>;学生罗尔诺的命令

用比较器可以吗?有人能帮我吗?谢谢你的每一个建议。 谢谢

更新:以下是完整的程序:

public class Student implements Comparable {

    int rollNo;
    String name;

    Student(String n,int rno) {
        rollNo=rno;
        name=n;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        TreeSet<Student> ts = new TreeSet<Student>();
        ts.add(new Student("bbb",2));
        ts.add(new Student("aaa",4));
        ts.add(new Student("bbb",2));
        ts.add(new Student("ccc",3));
        ts.add(new Student("aaa",1));
        ts.add(new Student("bbb",2));
        ts.add(new Student("bbb",5));

        System.out.println(ts);

    }

    @Override
    public int compareTo(Object obj) {
        Student s = (Student) obj;
        if (name.equals(s.name)) { // achieving uniqueness
            return 0;
        } else {
            if (rollNo < s.rollNo) {
                return -1;
            } else if (rollNo > s.rollNo) {
                return 1;
            } else {
                // this makes `name` the second ordering option.
                // names don't equal here
                return name.compareTo(s.name);
            }
        }
    }

    @Override
    public String toString() {
        return name + rollNo;
    }
}

更新:2:谢谢大家的建议,我还需要一些:)



/*
 * Actual scenario is having different properties,
 * So here I am just relating my actual scenario with Student class
 */
class Student implements Comparable {
    // sorting required on rollNo
    int rollNo;
    // Unique name is required
    String name;

    Student(String n, int rno) {
        rollNo = rno;
        name = n;
    }

    /**
     * 
     * @param args
     */
    public static void main(String[] args) {

        TreeSet<Student> tsName = new TreeSet<Student>();
        // here by default, order & uniqueness by name only
        tsName.add(new Student("ccc", 2));
        tsName.add(new Student("aaa", 4));
        tsName.add(new Student("ddd", 1));
        tsName.add(new Student("bbb", 3));
        tsName.add(new Student("ddd", 5));
        // output: aaa:4, bbb:3, ccc:2, ddd:1
        System.out.println(tsName);

        // creating new comparator for student RollNo
        TreeSet<Student> tsRollNo = new TreeSet<Student>(new Comparator<Student>() {
                    public int compare(Student stud1, Student stud2) {
                        return new Integer(stud1.rollNo).compareTo(stud2.rollNo);
                    }
                });
        tsRollNo.addAll(tsName);
        System.out.println(tsRollNo);
        // now got the desire output: ddd:1, ccc:2, bbb:3, aaa:4
    }

    public boolean equals(Object obj) {
        // internally not used to check equality while adding objects
        // in TreeSet
        System.out.println("equals() for " + this + " & " + ((Student) obj));
        return false;// return false/true doesn't make any sense here
    }

    @Override
    public int compareTo(Object obj) {
        Student s = (Student) obj;
        // internally inside TreeSet, compareTo is used to decide
        // whether two objects are equal or not,
        // i.e. compareTo will return 0 for same object(here student name)
        System.out.println("compareTo() for " + this + " & " + ((Student) obj));
        // achieving uniqueness
        return name.compareTo(s.name);
    }

    @Override
    public String toString() {
        return name + ":" + rollNo;
    }
}

输出

compareTo() for aaa:4 & ccc:2
compareTo() for ddd:1 & ccc:2
compareTo() for bbb:3 & ccc:2
compareTo() for bbb:3 & aaa:4
compareTo() for ddd:5 & ccc:2
compareTo() for ddd:5 & ddd:1
[aaa:4, bbb:3, ccc:2, ddd:1]
[ddd:1, ccc:2, bbb:3, aaa:4]

朋友们,无论我使用两个比较器得到什么,都可以 在添加对象时实现相同的效果?? 我不能先添加元素&;然后使用新的比较器实现所需的顺序。 我正在处理成千上万的价值观,所以也需要考虑绩效。


共 (4) 个答案

  1. # 1 楼答案

    抱歉来晚了,这里有一个优雅的解决方案:

        public class OwnSortedList<T> extends TreeSet<T> {
    
        private static final long serialVersionUID = 7109828721678745520L;
    
    
        public OwnSortedList(Comparator<T> levelScoreComparator) {
            super(levelScoreComparator);
        }
    
    
        public boolean add(T e) {
            boolean existsElement = false;
    
            Iterator<T> it = iterator();
            while(it.hasNext() && !existsElement){
                T nextElement = it.next();
                if(nextElement.equals(e)){
                    // Element found
                    existsElement = true;
                    Comparator<? super T> comparator = comparator();
                    int compare = comparator.compare(nextElement, e);
                    if(compare > 0){
                        remove(nextElement);
                        super.add(e);
                        //element added so return true
                        return true;
                    }
    
                }
            }
    
            if(!existsElement){
                super.add(e);
            }
    
            return false;
        }
    }
    
  2. # 2 楼答案

    订购

    TreeSet与指定的比较器一起使用answer by @ralph是一个很好的方法,请使用它

    设计

    您应该将“学生数据库”的概念封装在一个类中,该类公开并记录正确的行为,而不仅仅是使用原始集合。如果获得特定顺序的学生列表是一项设计要求,那么公开这样做的方法(可能返回^{

    • 维护一个或多个SetMaps按兴趣领域对学生进行排序/索引
    • 使用Arrays.sort()和指定的Comparator按需就地数组排序

    例如

    final class StudentTable {
       private static final Comparator<Student> studentRollNoComparator = ...;
       private final SortedSet<Student> sortedByRollNo = 
          new TreeSet<Student>(studentRollNoComparator);
    
       public Iterable<Student> studentsOrderedByRollNo()
       {
          return sortedByRollNo;
       } 
    
       //see below
       public void addStudent(final Student foo) { ... }
    }
    

    独特性

    您需要在Student类上重写equals()hashCode(),以便只比较学生名。然后你会在^{中获得唯一性(无声)。显然,如果你这样做,你需要在插入newStudent之前进行防御性编码,检查studentSet.contains(newStudent),这样你就知道你是否有一个重复的

    final class Student implements Comparable {
       ...
    
       @Override
       public boolean equals(Object o)
       {
          return o!=null &&  
                 o (instanceof Student) &&
                 ((Student)o).name.equals(this.name);
       }
    
       @Override
       public int hashCode()
       {
          return name.hashCode();  // good enough for this purpose
       } 
    }
    

    有了这个选项,插入student的代码可以如下所示:

    void addNewStudent(final Student toAdd)
    {
       if (studentSet.contains(toAdd)) { 
          throw new IllegalStateException("Student with same name as "+toAdd+" already exists.");
       }
    
       studentSet.add(toAdd);
    }
    

    然后,你的树集合中满是名字唯一的学生,如果没有,你的添加操作就会报告失败。(抛出异常只是一种可能的途径,只有当添加一个名字重复的学生实际上是一种例外情况时才合适,但您没有说。)

  3. # 3 楼答案

    TreeSet中,它将使用comparator,同时添加元素进行排序和唯一性检查

    现在的问题是,如果你对卷号使用比较器,你会让它按卷号和唯一卷号排序。你不能在树上同时拥有这两个

    我建议你去参加

    1. TreeSet在这里,您将集中讨论重复删除
    2. 一旦你有了唯一的数据,就去ArrayList按你想要的顺序排序
  4. # 4 楼答案

    你可以用不同的比较器初始化一个新的树集。-所以你需要做的就是编写一个新的比较器(实现java.util.Comparator接口),使用这个比较器初始化一个新的树集,然后将所有学生添加到这个集合中

    TreeSet<Student> sortedByRollNo new TreeSet<Student>(new RollNoComparator());
    sortedByRollNo.addAll(allStudents);
    
    TreeSet<Student> sortedByY new TreeSet<Student>(new YComparator());
    sortedByY.addAll(allStudents);
    

    每个树集都可以有自己的比较器进行排序,如果没有指定比较器,则树集使用集合元素的自然顺序

    添加了

    如果你只需要uniqe学生的名字,那么你有两种方法:

    • 以某种方式实现比较器,如果学生的名字等于,它将返回0(但我相信这是一种黑客行为)
    • 首先按姓名筛选学生,然后按rollNo排序

    有点像这样:

    TreeSet<Student> sortedByRollNo new TreeSet<Student>(new RollNoComparator());
    sortedByRollNo.addAll(new TreeSet<Student>(allStudends)); //this uses the native comparator to filter by uniqe name