问题描述
假设我需要 TreeSet
,其元素使用某些域逻辑排序。通过这个逻辑,一些元素的顺序并不重要,因此比较方法可以返回0,但在这种情况下我不能将它们放在 TreeSet
中。
Suppose I need TreeSet
with elements sorted with some domain logic. By this logic it doesn't matter order of some elements that doesn't equal so compare method can return 0, but in this case I couldn't put them in TreeSet
.
所以,问:我会从这样的代码中得到什么缺点:
So, question: what disadvantages I'll have from code like this:
class Foo implements Comparable<Foo>{}
new TreeSet<Foo>(new Comparator<Foo>(){
@Override
public int compare(Foo o1, Foo o2) {
int res = o1.compareTo(o2);
if(res == 0 || !o1.equals(o2)){
return o1.hashCode() - o2.hashCode();
}
return res;
}
});
更新:
确定。如果它应始终是方法之间的一致性 equals()
, hashcode()
和 compareTo()
,正如@SPFloyd - seanizer和其他人所说。
如果我将删除 Comparable
界面并在 Comparator
(我可以做到没有破坏封装)?所以它将是:
Ok. If it should always be a consistency between the methods equals()
, hashcode()
and compareTo()
, as @S.P.Floyd - seanizer and others said.If it would be better or even good if I'll remove Comparable
interface and move this logic in Comparator
(I can do it without broken encapsulation)? So it will be:
class Foo{}
new TreeSet<Foo>(new Comparator<Foo>(){
@Override
public int compare(Foo o1, Foo o2) {
//some logic start
if(strictliBigger(o1, o2)){ return 1;}
if(strictliBigger(o2, o1)){ return -1;}
//some logic end
if(res == 0 || !o1.equals(o2)){
return o1.hashCode() - o2.hashCode();
}
return res;
}
});
更新2 :
System.identityHashCode(x)
是否优于 hashCode()
如果我不需要稳定排序?
Would System.identityHashCode(x)
be better than hashCode()
if I don't need stable sort?
推荐答案
虽然这可能有用,但它远非最佳做法。
While this might work, it is far from being a best practice.
来自,但对于每个版本,还有第二个版本,其中包含自定义 Comparator
。如果您不使用自定义Comparator,您的列表元素需要在排序过程中实现 Comparable
或 RuntimeException
s 。
The Constructors are identical to those of ArrayList
, but for each of them there is also a second version with a custom Comparator
. If you don't use a custom Comparator, your list elements need to implement Comparable
or RuntimeException
s will occur during sorting.
public class SortedArrayList<E> extends ForwardingList<E> implements
RandomAccess{
private final class ListIteratorImpl extends ForwardingListIterator<E>{
private final int start;
public ListIteratorImpl(final int start){
this.start = start;
}
@Override
public void set(E element){throw new UnsupportedOperationException();}
@Override
public void add(E element){throw new UnsupportedOperationException();}
@Override
protected ListIterator<E> delegate(){return inner.listIterator(start);};
}
private Comparator<? super E> comparator;
private List<E> inner;
public SortedArrayList(){this(null, null, null);}
@SuppressWarnings("unchecked")
private SortedArrayList(
final List<E> existing,
final Collection<? extends E> values,
final Comparator<? super E> comparator
){
this.comparator =
(Comparator<? super E>)
(comparator == null
? Ordering.natural()
: comparator );
inner = (
existing == null
? (values == null
? new ArrayList<E>(values)
: new ArrayList<E>()
)
: existing;
}
public SortedArrayList(final Collection<? extends E> c){
this(null, c, null);
}
public SortedArrayList(final Collection<? extends E> c,
final Comparator<? super E> comparator){
this(null, c, comparator);
}
public SortedArrayList(final Comparator<? super E> comparator){
this(null, null, comparator);
}
public SortedArrayList(final int initialCapacity){
this(new ArrayList<E>(initialCapacity), null, null);
}
public SortedArrayList(final int initialCapacity,
final Comparator<? super E> comparator){
this(new ArrayList<E>(initialCapacity), null, comparator);
}
@Override
public boolean add(final E e){
inner.add(
Math.abs(
Collections.binarySearch(inner, e, comparator)
) + 1,
e
);
return true;
}
@Override
public void add(int i, E e){throw new UnsupportedOperationException();}
@Override
public boolean addAll(final Collection<? extends E> collection){
return standardAddAll(collection);
}
@Override
public boolean addAll(int i,
Collection<? extends E> es){
throw new UnsupportedOperationException();
}
@Override
protected List<E> delegate(){ return inner; }
@Override
public List<E> subList(final int fromIndex, final int toIndex){
return new SortedArrayList<E>(
inner.subList(fromIndex, toIndex),
null,
comparator
);
}
@Override
public ListIterator<E> listIterator(){ return new ListIteratorImpl(0); }
@Override
public ListIterator<E> listIterator(final int index){
return new ListIteratorImpl(index);
}
@Override
public E set(int i, E e){ throw new UnsupportedOperationException(); }
}
这篇关于比较器和等号()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!