2016-09-07 1 views
0

Привет, мне нужно получить идентификатор последней даты, содержащейся в Map.Как получить самую последнюю дату на карте <Long, Date>?

Идентификатор - уникальный номер Long, который идентифицирует дату.

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

Я заполнил карту таким образом:

mapRetrieveMostRecent.put(id, xDate); 

Я знаю, что TreeMap можно вставлять автоматически объекты сортировки по дате, но в моем случае сроки не являются уникальными. Любые предложения?

+0

Вы используете Java 8? –

+0

да Я @FranciscoTena – user2298581

+0

как вывод нужного вам списка ключей с одинаковой максимальной датой? –

ответ

0

Я знаю, что TreeMap можно вставлять автоматически объекты сортировки по дате , но в моем случае сроки не являются уникальными. Какие-либо предложения?

Одним из вариантов может быть использование TreeMultimap из Google гуавы, сортирует его ключи как 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, как вы можете иметь несколько записей, соответствующих тем же Date.


Вот как это может быть сделано в Java 8 с помощью Stream API:

Collection<Long> ids = mapRetrieveMostRecent.entrySet().stream() 
    .collect(Collectors.groupingBy(Map.Entry::getValue, TreeMap::new, toList())) 
    .lastEntry() 
    .getValue() 
    .stream() 
    .map(Map.Entry::getKey) 
    .collect(toList()); 
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; 
} 
+0

Ницца! Таким образом, в конце концов, у меня есть самая последняя дата, но как я могу получить доступ к его идентификационному ключу на карте? (к сожалению, мои даты не уникальны) – user2298581

+0

Вы можете перебрать набор ключей для этого, например: \t Карта mapRetrieveMostRecent = new HashMap (); \t Дата mostRecent = null, current; \t long mostRecentId = -1; \t для (длинный ID: mapRetrieveMostRecent.keySet()) { \t \t \t ток = mapRetrieveMostRecent.get (ID); \t if (mostRecent == null || current.after (mostRecent)) \t { \t \t mostRecent = текущий; \t \t mostRecentId = id; \t} \t} – uoyilmaz

+0

Это замечательно! Можете ли вы объяснить только значение «Дата mostRecent = null, current;» в конце инструкции MostRecent равно текущему? Как возможно, чтобы переменная имела два разных значения? Спасибо! @uoyilmaz – user2298581

1

Если вы используете Java8 я бы воспользоваться Сравнительное расширения, как это:

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

В вашем случае TreeMap будет сортировать по id, так как он сортирует а не значения.

Поскольку ваши объекты Date являются значениями, вы можете итерировать свою карту, пока не найдете последние Date.

Вот пример длинного иериста, повторяющий набор записей и получение идентификатора для последних Date.

Обратите внимание, что идентификатор в Date s не является уникальным, вы можете получать идентификатор для одного самых последних Date с, если у вас есть несколько 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 
+0

Рассмотрите возможность использования любых других конструкторов, таких как новая дата (длинная), а не добавление спящих в свой код. –

+0

@NicolasFilotto. Я согласен с принципом, но это только для тестирования. OP фактически будет иметь разные 'Date' для начала. – Mena

+0

@NicolasFilotto никогда не бывает, это красивее, как вы говорите - отредактировано. – Mena

3

Если вы ищете ключ максимальной даты вы можете использовать следующий Однострочник

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

Вы можете передавать записи и получить максимум с помощью компаратора:

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

Вы правы - хотя ОП не говорит, что он хочет в случае нескольких максимальных дат. – assylias

Смежные вопросы