Java 使用比较器的ConcurrentSkipListMap排序

Java 使用比较器的ConcurrentSkipListMap排序,java,sorting,collections,comparator,Java,Sorting,Collections,Comparator,我使用“ConcurrentSkipListMap”(因为我的环境将是多线程的)和“Comparator”根据插入对象的Id和日期对其进行排序。在“TestObject”中,其名称将是唯一的。所以我用它作为我在地图上的“钥匙”Id'将是任意值。我需要根据“Id”和“date”值对我的地图进行排序。(如果Id s相等,将按日期排序),因为这里我只添加当前日期,并将焦点放在Id字段上。但是map没有返回我期望的排序顺序 public class SortTest { private static

我使用“ConcurrentSkipListMap”(因为我的环境将是多线程的)和“Comparator”根据插入对象的Id和日期对其进行排序。在“TestObject”中,其名称将是唯一的。所以我用它作为我在地图上的“钥匙”Id'将是任意值。我需要根据“Id”和“date”值对我的地图进行排序。(如果Id s相等,将按日期排序),因为这里我只添加当前日期,并将焦点放在Id字段上。但是map没有返回我期望的排序顺序

public class SortTest {

private static final Comparator TEST_COMPARATOR = new TestComparator();
private static Map<String, TestObject> map = new ConcurrentSkipListMap<String, TestObject>();

private static class TestComparator<T> implements Comparator<TestObject> {

    @Override
    public int compare(TestObject o1, TestObject o2) {
        Integer x1 = o1.getId();
        Integer x2 = o2.getId();

        int Comp = x1.compareTo(x2);

        if (Comp != 0) {
            return Comp;
        } else {

            Date d1 = o1.getDate();
            Date d2 = o2.getDate();

            return d1.compareTo(d2);
        }
    }

}

public static void construct() {

    for (int i = 1; i <= 10; i++) {
        TestObject t = new TestObject();
        t.setId(i%3);
        t.setDate(new Date());
        t.setName("Obj_"+i);
        System.out.println(t);
        map.put(t.getName(),t);


    }

}
public static void main(String[] args) {
    SortTest x = new SortTest();
    x.construct();
    System.out.println(map);
}
}

我们的代码片段是-

{Obj_1=TestObject[name=Obj_1,id=1],Obj_10=TestObject[name=Obj_10,id=1],Obj_2=TestObject[name=Obj_2,id=2],Obj_3=TestObject[name=Obj_3,id=0]

预期订单为-

Obj_3(因为Id=0)、Obj_1、Obj_10(Id=1)、Obj_2(Id=2)


有人能指出我在这里做错了什么吗?提前谢谢。

地图比较的是键,而不是值。也就是说,它是按字母字符串顺序排列键的



另外,您还需要使用比较器作为构造函数参数来初始化映射。但在这种情况下,它将不起作用,因为比较器应该比较字符串(键)。

您尚未将比较器提供给
ConcurrentSkipListMap的构造函数

见:


因为比较器为空,所以实现使用键的自然顺序,在本例中为字符串值。

TreeMap和ConcurrentSkipListMap只能按键排序,如果您希望按不确定值排序,则可以在新实例传递的TestComparator时,使用构造方法创建内部比较器类“map”
private static map=new ConcurrentSkipListMap();
然后新建一个TreeMap,将参数映射到前面的“Comparator object”中。最后将“map”放到TreeMap中 代码如下:`public class SortTest{ 私有静态映射=新的ConcurrentSkipListMap()

私有静态类TestComparator实现Comparator{
MAPTMP;
公共TestComparator(映射){
this.tmp=map;
}
/*
*(非Javadoc)
* 
*@see java.util.Comparator#compare(java.lang.Object,java.lang.Object)
*/
公共整数比较(字符串o1、字符串o2){
整数x1=tmp.get(o1.getId();
整数x2=tmp.get(o2.getId();
int Comp=x1。与(x2)相比;
如果(组件!=0){
返回补偿;
}否则{
dated1=tmp.get(o1.getDate();
Date d2=tmp.get(o2.getDate();
返回d1。比较(d2);
}
}
}
公共静态void构造(){

for(int i=1;i
ConcurrentSkipListMap
是按键排序的,而不是按值排序的。坦率地说,我认为在Java中没有任何类型安全的方法可以让可变映射按值排序。即使我将该比较器传递给构造函数,这也不会被修复。需要想出一种方法来减去字符串前缀(“Obj”)比较一下,然后返回。我认为应该有效。
public class TestObject {

private String name;

private int id;

Date date;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public Date getDate() {
    return date;
}

public void setDate(Date date) {
    this.date = date;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

/* (non-Javadoc)
 * @see java.lang.Object#hashCode()
 */
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}



/* (non-Javadoc)
 * @see java.lang.Object#toString()
 */
@Override
public String toString() {
    return "TestObject [name=" + name + ", id=" + id + "]";
}

/* (non-Javadoc)
 * @see java.lang.Object#equals(java.lang.Object)
 */
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    TestObject other = (TestObject) obj;
    if (name == null) {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    return true;
}
private static class TestComparator<String> implements Comparator<String> {
    Map<String, TestObject> tmp;

    public TestComparator(Map<String, TestObject> map) {
        this.tmp = map;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
     */
    public int compare(String o1, String o2) {
        Integer x1 = tmp.get(o1).getId();
        Integer x2 = tmp.get(o2).getId();
        int Comp = x1.compareTo(x2);

        if (Comp != 0) {
            return Comp;
        } else {

            Date d1 = tmp.get(o1).getDate();
            Date d2 = tmp.get(o2).getDate();
            return d1.compareTo(d2);
        }
    }

}

public static void construct() {

    for (int i = 1; i <= 10; i++) {
        TestObject t = new TestObject();
        t.setId(i % 3);
        t.setDate(new Date());
        t.setName("Obj_" + i);
        System.out.println(t);
        map.put(t.getName(), t);

    }

}
public static void main(String[] args) {
    SortTest x = new SortTest();
    x.construct();
    System.out.println(map);
    TestComparator comparator = new TestComparator(map);
    TreeMap<String, TestObject> sorted_map = new TreeMap<String, TestObject>(comparator);
    sorted_map.putAll(map);
    System.out.println(sorted_map);
}