Hack:java.util.TreeSet中的重复项?

时间:2017-07-22 14:28:18

标签: java data-structures

我有一个简单的课程

public class A {
    int val;
    public A(int val) {this.val = val;}
}

我将A个实例存储在java.util.TreeSet中:

SortedSet<A> ss = new TreeSet<A>(new Comparator<A>() {
    @Override
    public int compare(A o1, A o2) {
        return Integer.compare(o1.val, o2.val);
    }
});

以后才能找到具有相同A值的val个实例无法在TreeSet中共存。

我需要TreeSet,因为我想:

  • 快速插入
  • 快速删除
  • 使用最小val
  • 快速查询元素

由于相等性完全取决于compare()的返回值0以及我们如何实现它,是否有一种黑客方式允许具有相同值val的实例在TreeSet中共存}?

我的解决方法是在val相等的情况下返回稳定的非零值,但事实证明它不稳定。

SortedSet<ListNode> ss = new TreeSet<ListNode>(new Comparator<ListNode>() {
    @Override
    public int compare(ListNode o1, ListNode o2) {
        if (o1.val != o2.val) return Integer.compare(o1.val, o2.val);
        return o1.hashCode() - o2.hashCode(); // not to return 0
    }
});

或者我应该切换到另一个数据结构? (如果存在一些比R-B树更好的替代品)

而且,哦,Geez,我知道modeling the mathematical set abstraction很酷,所有人都喜欢它。

结论:使用priority queue

2 个答案:

答案 0 :(得分:3)

这就是我想说的......为什么不使用文档所说的Queue,特别是PriorityQueue

  

实施说明:此实现为入队和出队方法提供O(log(n))时间:offer,poll,remove和add; remove(Object)和contains(Object)方法的线性时间;检索方法,窥视和大小的恒定时间。

PriorityQueue vs Tree中的差异也是第一个更轻,因为它使用binary heap而不是red-black tree;因此PriorityQueue将使用数组来存储其难以理解的数据。

另请注意,如果您经常使用高优先级任务填充PriorityQueue - 您的低优先级任务可能会在处理之前等待很长时间。

答案 1 :(得分:-2)

我想您希望不同的A实例在您的集合中共存,即使它们共享相同的val,也不要多次添加相同的A实例。

A a = new A(1);
A b = new A(1);
A c = new A(2);
A d = c;
ss.add(a);
ss.add(b);
ss.add(c);
ss.add(d);

之后,您希望ss包含三个实例:两个1值和一个2值(因为a和b是不同的实例,c和d包含相同的实例)。这就是你的代码将要做的事情(如果你不覆盖Object的hashCode()方法)。

只有一项改进:o1.hashCode() - o2.hashCode()可能会产生算术溢出,对该部分也更好地使用Integer.compare()。例如。尽管第一个数字更大,但2000000000 - (-2000000000)将给出否定结果。这将导致所有基于比较器的结构表现得异常。