简体   繁体   English

按日期排序HashMap

[英]Sorting a HashMap by date

In a Java class I have a method to reOrder an existing HashMap by date. 在Java类中,我有一个按日期重新编译现有HashMap的方法。 The HashMap is of a type <String, Object> where the Object contains a field called expPayDate and the key string is a sequential number turned into a string.. So I need to loop through the items in the sourceMap and find the item with the newest date then copy it to a tempMap in the correct order. HashMap的类型为<String, Object> ,其中Object包含一个名为expPayDate的字段,键字符串是一个序列号变成一个字符串。所以我需要循环遍历sourceMap中的项目并找到带有最新的日期然后以正确的顺序将其复制到tempMap。 My issue is what is the best way to determine the item with the newest date. 我的问题是确定具有最新日期的项目的最佳方法是什么。

Your best bet will be to use a SortedMap with the Comparator interface. 你最好的选择将是使用的SortedMap比较器接口。

Here is an example: 这是一个例子:

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

Use a TreeMap instead of HashMap. 使用TreeMap而不是HashMap。 it will be sorted automatically on insertion. 它会在插入时自动排序。

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

Alternatively, if you have an existing HashMap and want to create a TreeMap based on it, pass it to the constructor: 或者,如果您有一个现有的HashMap并想要基于它创建一个TreeMap,请将其传递给构造函数:

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

Hope it will help you. 希望它会对你有所帮助。

  1. Get all Entries by calling entrySet() method of Map 通过调用Map的entrySet()方法获取所有条目

  2. Create a custom Comparator to sort entries based upon values 创建自定义Comparator以根据值对条目进行排序

  3. Convert Entry set to List Entry设置转换为List

  4. Sort Entry list by using Collections.sort() method by passing your value comparator 通过传递值比较器,使用Collections.sort()方法对条目列表进行排序

  5. Create a LinkedHashMap by adding entries in sorted order. 通过按排序顺序添加条目来创建LinkedHashMap

Look at example code @ Sort HasMap by value 按值查看示例代码@ Sort HasMap

For simplicity I am assuming that type of your map is something more like Map<String, MyClass> map where MyClass has method like getDate() which returns expPayDate . 为简单起见,我假设您的地图类型更像Map<String, MyClass> map ,其中MyClass具有getDate()方法,返回expPayDate

My issue is what is the best way to determine the item with the newest date. 我的问题是确定具有最新日期的项目的最佳方法是什么。

If you want to find single map entry which value contains max date you don't need to sort entire map which at best would give you O(n*logn). 如果你想找到哪个包含最大日期的单个地图条目, 你不需要对整个地图进行排序 ,最多只能给你O(n * logn)。 What you need is simple iteration of all elements in map and comparing them with current max, which will be O(n) operation. 你需要的是对map中所有元素的简单迭代,并将它们与当前max进行比较,这将是O(n)操作。

You can use stream() (functionality added in Java 8) and its max method. 您可以使用stream() (Java 8中添加的功能)及其max方法。 This method needs Comparator and you can easily create one by using comparing method and passing lambda expression which will return value which should be used when comparing. 这个方法需要Comparator ,你可以通过comparing方法和传递lambda表达式轻松创建一个,这将返回比较时应该使用的值。

So your code can look like 所以你的代码看起来像

//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();

If you can't use Java 8 you can write your own method which will iterate over elements and find max. 如果你不能使用Java 8,你可以编写自己的方法,它将迭代元素并找到最大值。 Such method can look like 这种方法看起来像

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

and you can use it like 你可以像使用它一样

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

If you just need the minimum or maximum date, a simple for each loop might be sufficient: 如果您只需要最小或最大日期,则每个循环的简单可能就足够了:

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

This way complexity is only O(n) and insert and delete operations are cheaper than using a sortedMap . 这种方式复杂性只有O(n),插入和删除操作比使用sortedMap便宜。 Anyway, I think patstuart 's suggestion (using a sortedMap ) is more elegant. 无论如何,我认为patstuart的建议(使用sortedMap )更优雅。

The correct solution depends on your performance constraints. 正确的解决方案取决于您的性能限制。

If your issue is just finding the item with the newest date, then if O(n) performance is OK you can do a scan of the values() in your HashMap and find the minimum that way. 如果您的问题只是找到具有最新日期的项目,那么如果O(n)性能正常,您可以在HashMap中扫描values()并找到最小值。

It depends on how often you need to do this relative to other access on the data structure. 这取决于您相对于数据结构上的其他访问需要执行此操作的频率。 It would be perfectly reasonable to use a SortedMap or use a secondary data structure such as a PriorityQueue (acting as a heap on the date), depending on your access patterns for this data structure. 使用SortedMap或使用辅助数据结构(例如PriorityQueue(在日期充当堆))将是完全合理的,具体取决于您对此数据结构的访问模式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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