Сортировка ConcurrentSkipListMap с использованием компаратора - PullRequest
2 голосов
/ 30 марта 2012

Я использую 'ConcurrentSkipListMap' (поскольку моя среда будет многопоточна) и 'Comparator' для сортировки вставляемого объекта в соответствии с его идентификатором и датой.в «TestObject» его имя будет уникальным.поэтому я использовал его в качестве своего «ключа» на карте.«Id» будет произвольным значением.мне нужно отсортировать карту по значениям 'Id' и 'date' (если Id будут равны, я отсортирую их по дате), так как здесь я просто добавляю текущую дату и фокусируюсь на поле ID.Но карта не вернула мне порядок сортировки, которого я ожидаю.

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

}

И ObjectClass это -

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

}

Фрагмент из - это *

{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, (идентификаторы = 1), Obj_2 (Id= 2)

Может кто-нибудь указать мне, что я здесь не так делаю?Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 30 марта 2012

Карта сравнивает ключи, а не значения. То есть это упорядочено в алфавитном порядке для ключей.


P.S. Также вам нужно инициализировать карту с помощью компаратора в качестве параметра конструктора. Но в этом случае это не сработает, поскольку компаратор должен сравнивать строки (ключи).

1 голос
/ 30 марта 2012

Вы не предоставили Компаратор конструктору вашего ConcurrentSkipListMap.

См .:

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

Поскольку компаратор имеет значение null, реализацияиспользует естественный порядок ключей, которые в данном случае являются строковыми значениями.

0 голосов
/ 16 февраля 2016

TreeMap и ConcurrentSkipListMap могут сортировать только по ключу. Если вы хотите отсортировать по неопределенным значениям, вы можете создать внутренний класс Comparator с помощью метода конструирования, когда вы создаете новый экземпляр TestComparator, вы передаете «map»TreeMap параметр с предыдущим «объектом Comparator». Наконец, поместите «карту» в код TreeMap следующим образом: `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);
}

}`

Я не думаю об эффективности кода, он просто реализует функцию.

...