Сортировка HashMap по дате

в классе Java у меня есть метод для изменения порядка существующего HashMap по дате. HashMap имеет тип <String, Object> где объект содержит поле с именем expPayDate, а строка ключа-последовательный номер, превращенный в строку.. Поэтому мне нужно перебрать элементы в исходной карте и найти элемент с самой новой датой, а затем скопировать его в tempMap в правильном порядке. Моя проблема заключается в том, как лучше всего определить элемент с новейшей датой.

6 ответов


используйте TreeMap вместо HashMap. он будет отсортирован автоматически при вставке.

Map< Date, Object> m = new TreeMap< Date, Object>();

кроме того, если у вас есть существующая HashMap и вы хотите создать на ее основе TreeMap, передайте его конструктору:

Map< Date, Object> sortedMap = new TreeMap< Date, Object>(m);

надеюсь, что это поможет вам.


лучше использовать SortedMap С компаратор интерфейс.

вот пример:

public SortedMap<String, Object> getSortedMap(Map<String, Object> originalMap) {
    SortedMap<String, Object> tmpMap = new TreeMap<String, Object>(new Comparator<String>(){
        @Override
        public int compare(String key1, String key2) {
            //logic for comparing dates
        }           
    });
    tmpMap.putAll(originalMap);
    return tmpMap;
}

для простоты я предполагаю, что тип вашей карты больше похож на Map<String, MyClass> map здесь MyClass есть способ как getDate() возвращает expPayDate.

моя проблема - это лучший способ определить элемент с новейшей датой.

если вы хотите найти одну запись карты стоимостью содержит максимальную дату вам не нужно сортировать всю карту что в лучшем случае даст вам O(n*logn). То, что вам нужно, просто итерация всех элементов карты и сравнение их с текущим max, который будет o(n) операция.

можно использовать stream() (функциональность добавлена в Java 8) и его max метод. Этот метод требует Comparator и вы можете легко создать с помощью comparing метод и передача лямбда-выражения, которое возвращает значение, которое должно использоваться при сравнении.

так что ваш код может выглядеть как

//import java.util.Map.Entry;

Optional<Entry<String, MyClass>> max = map.entrySet().stream()
        .max(Comparator.comparing(e -> e.getValue().getDate()));

Entry<String, MyClass> entry = max.get();
MyClass maxMC = entry.getValue();

если вы не можете использовать Java 8, вы можете написать свой собственный метод, который будет перебирать элементы и найти максимум. Такой метод может выглядеть как

public static <T> T max(Iterable<T> iterable, Comparator<T> comp) {
    Iterator<T> it = iterable.iterator();
    T max = null;
    if (it.hasNext()) {
        max = it.next();
    }
    while (it.hasNext()) {
        T tmp = it.next();
        if (comp.compare(max, tmp) < 0)
            max = tmp;
    }
    return max;
}

и вы можете использовать его как

Comparator<Entry<String, MyClass>> myComparator = new Comparator<Entry<String, MyClass>>() {
    @Override
    public int compare(Entry<String, MyClass> o1, Entry<String, MyClass> o2) {
        return o1.getValue().getDate().compareTo(o2.getValue().getDate());
    }
};
Entry<String, MyClass> maxEntry = max(map.entrySet(), myComparator);
MyClass max = maxEntry.getValue();

  1. получить все записи, позвонив entrySet() способ карты

  2. создать пользовательское Comparator сортировать записи на основе значений

  3. преобразование Entry значение List

  4. сортировка списка записей с помощью Collections.sort() метод, передавая ваш компаратор значений

  5. создать LinkedHashMap путем добавления записей в отсортированном порядке.

посмотреть пример кода @ Сортировать HasMap по значению


Если вам просто нужна минимальная или максимальная дата, может быть достаточно простого для каждого цикла:

Date maxDate = null;
for (Entry<String, Object> item: hashMap.entrySet()) 
    if (maxDate == null || maxDate before((Date)item.getValue())) 
        maxDate = (Date)item.getValue();

таким образом, сложность только O (n), а операции вставки и удаления дешевле, чем использование sortedMap. Во всяком случае, я думаю patstuartпредложение (используя sortedMap) более элегантный.


правильное решение зависит от ваших ограничений производительности.

Если ваша проблема заключается в поиске элемента с новейшей датой, то если производительность O (n) в порядке, вы можете выполнить сканирование значений () в вашем HashMap и найти минимум таким образом.

Это зависит от того, как часто вам нужно делать это относительно другого доступа к структуре данных. Было бы вполне разумно использовать SortedMap или использовать вторичную структуру данных, такую как PriorityQueue (действуя как куча на дату), в зависимости от ваших шаблонов доступа для этой структуры данных.