如何在Map <long,date =“”>中获取最新日期?

时间:2016-09-07 10:18:10

标签: java date collections hashmap treemap

您好我需要获取Map中包含的最新日期的ID。

ID是唯一的Long数字,用于标识日期。

Map<Long, Date> mapRetrieveMostRecent= new HashMap<Long, Date>();

我用这种方式填充了地图:

mapRetrieveMostRecent.put(id, xDate);

我知道TreeMap可以自动插入按日期排序的对象,但在我的情况下,日期并不是唯一的。 有什么建议吗?

6 个答案:

答案 0 :(得分:3)

如果您要查找最大日期的关键字,可以使用以下单行

Long keyMax = Collections.max(mapRetrieveMostRecent.entrySet(), Map.Entry.comparingByValue()).getKey();

答案 1 :(得分:1)

如果可行,您可以在O(n)中迭代地图中的值:

Map<Long, Date> mapRetrieveMostRecent= new HashMap<Long, Date>();
Date mostRecent = null;
for( Date d : mapRetrieveMostRecent.values())
{
    if( mostRecent == null || d.after( mostRecent))
        mostRecent = d;
}

答案 2 :(得分:1)

如果你使用的是Java8,我会利用这样的Comparable扩展:

 public static <K, V extends Comparable<? super V>> Map<K, V>  sortByValue( Map<K, V> map ){
     List<Map.Entry<K, V>> l = new LinkedList<>( map.entrySet() );
     Collections.sort(l, new Comparator<Map.Entry<K, V>>()
     {
         @Override
         public int compare( Map.Entry<K, V> one, Map.Entry<K, V> another )
         {
             return (one.getValue()).compareTo( another.getValue() );
         }
     } );

     Map<K, V> r = new LinkedHashMap<>();
     for (Map.Entry<K, V> item : l)
     {
         r.put( item.getKey(), item.getValue() );
     }
     return r;
 }

当我得到这个解决方案时,我正在尝试Stream课程:

 Map<Long, Date> mapRetrieveMostRecent= new HashMap<>();
 Calendar cal = Calendar.getInstance();
 mapRetrieveMostRecent.put(1l, cal.getTime());
 cal.add(Calendar.DAY_OF_MONTH, -1);
 mapRetrieveMostRecent.put(2l, cal.getTime());
 cal.add(Calendar.DAY_OF_MONTH, 4);
 mapRetrieveMostRecent.put(3l, cal.getTime());

 Map<Long, Date> mapRetrieveMostRecentOrdered = sortMap(mapRetrieveMostRecent);
 System.out.println("Sorted Map Ascending: " + Arrays.toString(mapRetrieveMostRecentOrdered.entrySet().toArray()));

 public static <K, V extends Comparable<? super V>> Map<K,V> sortMap( Map<K,V> map){
        return map.entrySet().stream()
            .sorted(Map.Entry.comparingByValue())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (e1, e2) -> e2, LinkedHashMap::new));
 }

相应的测试:

@Test
public void testSortByValue()
{
    int testSize = 50;
    Random random = new Random(System.currentTimeMillis());
    Map<Long, Date> testMap = new HashMap<>(testSize);
    for(long i = 0 ; i < testSize ; ++i) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, random.nextInt());
        testMap.put(i, cal.getTime());
    }

    testMap = TenaTest.sortByValue( testMap );//Using compare
  //testMap = TenaTest.sortMap( testMap );//Using streams
    Assert.assertEquals( testSize, testMap.size() );

    Date previous = null;
    for(Map.Entry<Long, Date> entry : testMap.entrySet()) {
        Assert.assertNotNull( entry.getValue() );
        if (previous != null) {
            Assert.assertTrue( entry.getValue().after(previous) );
        }
        previous = entry.getValue();
    }
}

答案 3 :(得分:1)

在您的情况下,TreeMap将按id排序,因为它会对键进行排序,而不是值。

由于您的Date个对象是值,您可能需要迭代地图,直到找到最新的Date

这是一个长期的例子,它迭代条目集并检索最新Date的ID。

请注意,Date的ID不是唯一的,如果您有多个,则可能会获得最新Date一个的ID与其他人相比,Date是平等且最新的。

// your map
Map<Long, Date> map = new HashMap<Long, Date>();
// putting values
map.put(0l, new Date());
// putting values
map.put(0l, new Date(0l));
map.put(1l, new Date(1l));
map.put(2l, new Date(2l)); // this will be the most recent
Date latest = null;
Long latestID = null;
// iterating entry set
for (Map.Entry<Long, Date> entry : map.entrySet()) {
    Date value = entry.getValue();
    Long key = entry.getKey();
    // initial comparison
    if (latest == null) {
        latest = value;
        latestID = key;
        continue;
    }
    // further comparisons
    if (value.after(latest)) {
        latest = value;
        latestID = key;
    }
}
System.out.println(latestID); // will print 2

答案 4 :(得分:1)

您可以使用比较器流式传输条目并获得最大值:

Map<Long, Date> mapRetrieveMostRecent = new HashMap<Long, Date>();
mapRetrieveMostRecent.entrySet().stream()
                     .max(Entry::comparingByValue)
                     .map(Entry::getKey)
                     .orElse([default value here]);

答案 5 :(得分:0)

  

我知道TreeMap可以自动插入按日期排序的对象   但就我而言,日期并不是唯一的。有什么建议吗?

一种选择可能是使用 Google Guava 中的TreeMultimap,它会像TreeMap一样对其键进行排序,并接受重复值,以使其适用于您的情况你必须将键和值反转为下一个:

// Create my map
TreeMultimap<Date, Long> mapRetrieveMostRecent =  TreeMultimap.create();
...
// Put an entry into my map
mapRetrieveMostRecent.put(xDate, id);
...
// Get all the ids corresponding to the most recent date
Collection<Long> ids = mapRetrieveMostRecent.asMap().lastEntry().getValue();

使用此方法,您将获得与最新 Date相对应的所有ID ,因为您可以将多个ID匹配到同一Date

以下是使用Stream API Java 8 中完成的方法:

Collection<Long> ids = mapRetrieveMostRecent.entrySet().stream()
    .collect(Collectors.groupingBy(Map.Entry::getValue, TreeMap::new, toList()))
    .lastEntry()
    .getValue()
    .stream()
    .map(Map.Entry::getKey)
    .collect(toList());