1

我有一个对象列表。该对象看起来类似于这个:

class Data {

    ...

    private X somethig;
    private Y somethigElse;

    public boolean customEquals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Data)) {
            return false;
        }
        Data other = (Data) obj;
        if (something == null) {
            if (other.something != null) {
                return false;
            }
        } else if (!something.equals(other.something)) {
            return false;
            }
        if (somethigElse == null) {
            if (other.somethigElse != null) {
            return false;
            }
        } else if (!somethigElse.equals(other.somethigElse)) {
            return false;
        }
        return true;       
    }

    public boolean equals(Object obj) {
        ...
    }

    public int hashCode() {
        ...
    }

    getters/setters

}

我需要过滤列表以从中获取不同的对象。

请注意,实现了 equals 和 hashCode 方法(它们使用另一个字段),我不能在此任务中使用 equals。所以相等性不是由 equals 定义的,而是由 'something' 和 'somethigElse' 属性定义的。我怎样才能做到这一点?

我努力了:

final Comparator<Data> comparator = new Comparator<Data>() {

    @Override
    public int compare(Data o1, Data o2) {
            return o1.customEquals(o2) ? 0 : 1;
    }
};
Set<Data> set = new TreeSet<Data>(comparator);
set.addAll(list);
System.out.println(set);

但是该集合仍然多次包含一些对象。

4

2 回答 2

3

那是因为您没有提供正确的排序功能。

TreeSet排序算法做了一些假设,比如:

compare(a, b) > 0 => compare(b, a) < 0
compare(a, b) > 0 && compare(b, c) > 0 => compare(a, c) > 0

等等。

实施适当的比较,而不仅仅是“等于”,它应该可以工作。

final Comparator<Data> comparator = new Comparator<Data>() {

    @Override
    public int compare(Data o1, Data o2) {
        int k = o1.getSomething().compareTo(o2.getSomething();
        if (k != 0) {
            return k;
        }
        return o1.getSomethingElse() - o2.getSomethingElse();
    }
};

那是因为TreeSet是 a SortedSet,并且您说到达的每个新元素都比其他元素要大,除了它自己。

让我们做一个简化,用一个简短的例子来说明正在发生的事情,假设我们只使用数字和比较器,并且存储是一个数组(和二进制搜索)而不是树,因为它更容易表示。

我们得到了 number 1,它是唯一的元素,所以[1]现在是数组。

我们0现在得到一个,但是当你告诉集合它更大时,我们得到[1, 0].

例如,让我们现在添加一个 3,我们将得到[1, 0, 3].

添加另一个1,二等分将尝试将其与中间元素进行比较,0发现它更大,转到另一半,与 比较,3它再次更大,所以我们得到[1, 0, 3, 1]

如果我们添加另一个1,现在它会看到该元素已经存在并且不会添加它,但是如果您添加任何其他数字并且碰巧它的重复不在任何二等分点中,它将始终以数组的末尾。

于 2013-07-31T12:40:03.023 回答
1

可能你需要修复你的compare()

public int compare(Data o1, Data o2)
{
  int i = o1.getSomething().compareTo(o2.getSomething());
  if (i != 0) return i;
  return o1.getSomethingElse()- o2.getSomethingElse();
}
于 2013-07-31T12:43:41.420 回答