我需要一组排序的对象,目前正在使用TreeSet
. 我的问题是compareTo
对象经常会返回0
,这意味着这两个对象的顺序保持不变。TreeMap
(TreeSet
默认情况下使用)然后将它们视为同一个对象,这是不正确的。
我可以使用什么替代品TreeMap
?
用例:我有一组可显示的对象。我想按 Y 坐标对它们进行排序,以便它们以正确的顺序呈现。当然,两个对象很可能具有相同的 Y 坐标。
我需要一组排序的对象,目前正在使用TreeSet
. 我的问题是compareTo
对象经常会返回0
,这意味着这两个对象的顺序保持不变。TreeMap
(TreeSet
默认情况下使用)然后将它们视为同一个对象,这是不正确的。
我可以使用什么替代品TreeMap
?
用例:我有一组可显示的对象。我想按 Y 坐标对它们进行排序,以便它们以正确的顺序呈现。当然,两个对象很可能具有相同的 Y 坐标。
您正在定义一个要比较的标准,但您需要添加额外的标准。
你说:
我有一组可显示的对象。我想按 Y 坐标对它们进行排序,以便它们以正确的顺序呈现。当然,两个对象很可能具有相同的 Y 坐标。
所以,如果两个元素有相同的 Y 坐标,你先放什么?其他标准是什么?
可能是创建时间,也可能是 x 坐标,你只需要定义它:
Map<String,Thing> map = new TreeMap<String,Thing>(new Comparator<Thing>(){
public int compare( Thing one, Thing two ) {
int result = one.y - two.y;
if( result == 0 ) { // same y coordinate use another criteria
result = one.x - two.x;
if( result == 0 ) { //still the same? Try another criteria ( maybe creation time
return one.creationTime - two.creationTime
}
}
return result;
}
});
您必须定义一个Thing
高于/低于/等于/何时高于另一个Thing
。如果其中一个属性与其他属性相同,则可能您不应该移动它们。如果有其他属性比较使用它。
您遇到的问题是compareTo
返回0
意味着对象是相等的。同时,您将它们放入一个集合中,这不允许相同元素的多个副本。
要么重写你的compareTo
,以便不相等的元素返回不同的值,要么使用类似 a 的东西,java.util.PriorityQueue
它允许相等元素的多个副本。
我以前做过。它是一个有序的多图,它只是一个 List 对象的 TreeMap。像这样..
Map<KeyType, List<ValueType>> mmap = new TreeMap<KeyType, List<ValueType>>();
每次引入新键时,您都需要构造一个新的 LinkedList,因此将其包装在自定义容器类中可能会有所帮助。我会试着找到一些东西。
所以,我很快就把这个自定义容器放在一起(完全未经测试),但它可能是你要找的。请记住,如果您确实在寻找值列表的有序映射,则应该只使用这种类型的容器。如果您的值有一些自然顺序,则应按照其他人的建议使用 TreeSet。
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class MTreeMap<K, V> {
private final Map<K, List<V>> mmap = new TreeMap<K, List<V>>();
private int size = 0;
public MTreeMap() {
}
public void clear() {
mmap.clear();
size=0;
}
public boolean containsKey(K key) {
return mmap.containsKey(key);
}
public List<V> get(K key) {
return mmap.get(key);
}
public boolean isEmpty() {
return mmap.isEmpty();
}
public Set<K> keySet() {
return mmap.keySet();
}
public Collection<List<V>> valueLists() {
return mmap.values();
}
public void put(K key, V value) {
List<V> vlist = mmap.get(key);
if (null==vlist) {
vlist = new LinkedList<V>();
mmap.put(key, vlist);
}
vlist.add(value);
++size;
}
public List<V> remove(Object key) {
List<V> vlist = mmap.remove(key);
if (null!=vlist) {
size = size - vlist.size() ;
}
return vlist;
}
public int size() {
return size;
}
public String toString() {
return mmap.toString();
}
}
这是一个基本的测试:
public class TestAnything {
public static void main(String[] args) {
MTreeMap<Integer, String> mmap = new MTreeMap<Integer, String>();
mmap.put(1, "Value1");
mmap.put(2, "Value2");
mmap.put(3, "Value3");
mmap.put(1, "Value4");
mmap.put(3, "Value5");
mmap.put(2, "Value6");
mmap.put(2, "Value7");
System.out.println("size (1) = " + mmap.get(1).size());
System.out.println("size (2) = " + mmap.get(2).size());
System.out.println("size (3) = " + mmap.get(3).size());
System.out.println("Total size = " + mmap.size());
System.out.println(mmap);
}
}
输出是这样的:
size (1) = 2
size (2) = 3
size (3) = 2
Total size = 7
{1=[Value1, Value4], 2=[Value2, Value6, Value7], 3=[Value3, Value5]}
我有一个自己的想法,但这更像是一种解决方法
int compare(Object a, Object b) {
an = a.seq + (a.sortkey << 16); // allowing for 65k items in the set
bn = b.seq + (a.sortKey << 16);
return an - bn; // can never remember whether it's supposed to be this or b - a.
}
使用排序集(例如 TreeSet)时要记住两件重要的事情:
1)它们是集合;同一个集合中不允许有两个相等的元素
2)平等必须与比较机制一致(无论是比较器还是可比较的)
因此,在您的情况下,您应该通过添加一些辅助排序标准来“打破关系”。例如:首先使用 Y 轴,然后是 X,然后是一些唯一的对象标识符。