简体   繁体   中英

ConcurrentSkipListMap Sorting Using Comparator

I am using 'ConcurrentSkipListMap' (Since my environment will be multythreaded) and a 'Comparator' to sort the inserting object according to its Id & date. in the 'TestObject' its Name will be unique. so i used it as my 'key' in the map. 'Id' will be a arbitrary value. i need to sort my map according to the 'Id' and 'date' values.(if Id s are equal will sort it by date) for here i just add current date and gave the focus on the ID field. But map didn't return me the sorting order i expect.

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);
}

}

And the ObjectClass is -

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;
}

}

Out snippet is -

{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],......

Expected Order is -

Obj_3(Since Id =0 ),Obj_1,Obj_10, (Ids are =1 ), Obj_2 (Id =2)

Can anyone please point me out what i am doing wrong here? Thanks in advance.

The map compares keys, not values. Ie it is ordered in alphabet string order for keys.


PS also you need to initialize the map with the comparator as a constructor parameter. But in this case it won't work, as comparator should compare Strings (keys).

You haven't supplied the Comparator to the constructor of your ConcurrentSkipListMap .

See:

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentSkipListMap.html

Because the Comparator is null, the implementation uses the natural ordering of the keys, which in this case are String values.

TreeMap and ConcurrentSkipListMap can only sort by Key,if you want sort by uncertain Values ,you can create an inner Comparator class with a construction method ,when you new instance the TestComparator you pass the "map" private static Map<String, TestObject> map = new ConcurrentSkipListMap<String, TestObject>(); Then new a TreeMap the parameter with previous "Comparator object".At last put the "map" to TreeMap code like this:`public class SortTest { private static Map map = new ConcurrentSkipListMap();

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);
}

}`

I don't think about the efficiency of the code ,it just realizes the function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM