我不能遍历TreeSet

时间:2014-02-28 23:29:05

标签: java

我必须将用他的id标识的User添加到set中,并且在运行时,所有用户表单都必须按此id排序。

我已经创建了TreeSet添加了一些User对象,并尝试迭代它。

这是我的尝试:

//irrelevant code removed

    TreeSet<User> userSet = new TreeSet<User>();
    userSet.add(new User(2));
    userSet.add(new User(1));
    userSet.add(new User(3));

    Iterator<User> iterator = userSet.iterator();

    while (iterator.hasNext()) {
        System.out.print(iterator.next() + " ");
    }

我写了类User,其中一个是字段id,构造函数有id作为参数。

public class User {
    private int id;

    // irrelevant code removed

    public User(int id) {
        this.id = id;
    }

    // irrelevant code removed

    public String toString() {
        return id + "";
    }
}

当我运行此代码时,我得到ClassCastException。

这是stacktrace:

Exception in thread "main" java.lang.ClassCastException: OrderedUsers$User cannot be cast to java.lang.Comparable
    at java.util.TreeMap.compare(TreeMap.java:1188)
    at java.util.TreeMap.put(TreeMap.java:531)
    at java.util.TreeSet.add(TreeSet.java:255)
    at OrderedUsers.<init>(OrderedUsers.java:9)
    at Main.main(Main.java:6)

我做错了什么?

4 个答案:

答案 0 :(得分:4)

当您决定使用TreeSet时,您的方法正确,因为使用TreeSet可以获得有序输出。但... 请注意,如果使用TreeSet,由于TreeSet已排序,您必须实现Comparable

当您实施Comparable时,您将得到您期望的结果。

我建议您执行以下更改:

public class User implements Comparable<User> {
    private int id;

    // irrelevant code removed

    public User(int id) {
        this.id = id;
    }

    // irrelevant code removed

    public String toString() {
        return id + "";
    }

    @Override
    public int compareTo(User u) {
        return id - u.id;
    }
}

答案 1 :(得分:2)

将自定义Comparator传递给TreeSet constructor或在模型类中实施Comparable

TreeSet维护排序顺序,需要知道如何比较User

答案 2 :(得分:2)

TreeSet通过执行与二进制搜索树(实际上是红黑树)类似的现有对象来内部存储对象。因此,您需要在User中实现Comparable接口,或者为TreeSet提供自定义Comparator。

如果您不希望用户对象以排序顺序存储,我建议使用ArrayList。

方法1:

 public class User implements Comparable<User>
 {
    public int compare(User u)
    {
        if( u == null)
           return 1;

        return id - u.id;
    }
 }

方法2:

  public class CompareUsers implements Comparator<User>
  {
        public int compareTo(User a, User b)
        {
           if(a == null)
              return -1;
           if(b == null)
               return 1;

           return  a.id - b.id;
        }

  }

   // Create an instance of this comparator class and pass to the TreeSet 
   // during initialization.

   TreeSet<User> userSet = new TreeSet<User>(new CompareUsers());

答案 3 :(得分:2)

以下是TreeMap.java 1188的陈述:

    return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
        : comparator.compare((K)k1, (K)k2);

因此,如果comparatornull,那么它会尝试将集合成员转换为(Comparable)。如果您的班级未实施Comparable,则会导致您看到的ClassCastException。仅当您调用提供comparator的{​​{1}}构造函数时(或者如果您从已有比较器的另一个TreeMap复制它),Comparator才为非null。