2014-09-04 3 views
2

У меня есть List из Stat объектов, и каждый Stat имеет поле Date. Этот список может быть очень большим. То, что я хотел бы сделать, - организовать эти объекты в диапазонах дат (недели, чтобы быть конкретными) эффективно. Итак, если на той же неделе происходят два объекта, они переходят в один и тот же List. Для простоты «недельные» интервалы уже определены, поэтому вам не нужно беспокоиться о том, чтобы подходить к диапазонам.Организация объектов по дате в Java

Итак, вот мой нынешний подход. У меня есть LinkedHashMap<Date, List<Stat>>, который содержит все даты, которые мне нужны в порядке возрастания, и каждая запись инициализируется пустым ArrayList. Я думаю о каждом Stat, итерации по всему набору записей на карте и отслеживанию ближайшей даты, когда stat также больше или равен. Тогда это будет что-то вроде map.get(closestDate).add(stat).

Кажется, что должен быть лучший способ сделать это. Возможно, создайте что-то вроде findClosestKeyGreaterThanOrEqualTo, так что мне не нужно каждый раз перебирать всю карту?

Любые идеи?

+0

Может вы лучше понимаете, что именно хотите? Очевидно, что новая статистика должна быть вставлена ​​на той же неделе, что и та, чьи данные наиболее близки? – djechlin

+0

Таким образом, ключи карты могут быть «Март 3», «Мар 10», «Март 17» и т. Д. Если стат имеет дату «11 марта», он пойдет в список по дате «Мар 10». «Мар 10» - самая близкая дата, что «11 марта» также больше ... Я думаю, что имя гипотетической функции может быть более ясным. – jlars62

ответ

2

Вы можете использовать NavigableMap (например, TreeMap), который имеет very useful methods именно для этой цели.

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

NavigableMap<Date, List<Stat>> map = new TreeMap<>(); 
// add all your weekly values associated with empty lists 

Тогда для каждого из ваших Stat объектов, найти нужный список просто:

final Entry<Date, List<Stat>> entry = map.floorEntry(stat.getDate()); 
entry.getValue().add(stat); 
+0

Я придумал это перед тем, как вы разместили его. Но вы объяснили это лучше меня, поэтому я приму ваш ответ. – jlars62

+0

Вы правы, теперь я понимаю, что вы ответили на свой вопрос быстрее, чем я, и вы указали правильный метод «floorKey», а не неправильный «floorEntry», который я использовал; Я старею ... :) –

+0

@ jlars62 Я отредактировал фрагмент кода, чтобы показать свое первоначальное намерение относительно 'floorEntry', только для записи. –

1

Вот что я хотел бы сделать, если вы уже можете конвертировать даты в weekId:

  • Создать Map<WeekId, List<Stat>>
  • перебирать оригинал List<Stat> один раз и в каждом цикле расчета weekId с даты, то добавить Stat в соответствующий список путем извлечения его из Map по weekId (создать, если он не существует, и добавить его к карте)

Вы должны получить желаемый результат на карте в конце цикла.

1

Убедитесь, что все даты округлены до ближайшей недели. Затем используйте функцию getWeek(stat) и вставьте stat в карту. Простой HashMultimap будет делать.

Вам необходимо решить проблему хеш-кодов и равенства. Скажем, у меня есть тип

class Pair { 
    public int x; 
    public int y; 
    // obvious constructor 
} 

данных Обратите внимание:

new Pair(1,2) == new Pair(1,2) // false 
new Pair(1,2).equals(new Pair(1,2)) // false 

И если вы используете их в качестве ключей в хэш-карте они будут разные ключи.

Чтобы преодолеть это, вам необходимо переопределить equals и hashCode.

Для Date мы наблюдаем:

public boolean equals(Object obj) { 
    return obj instanceof Date && getTime() == ((Date) obj).getTime(); 
} 

Hashcode будет определяться соответственно. Поэтому, если вы отключаете Date, вы получите только то, что хотите, если даты согласны с миллисекундом.

Поэтому

HashMultimap<Date, Stat> map; 

прекрасно, но вы должны программно соблюдать соглашение, что все даты округляется до ближайшей недели. Затем выполните:

Date key = roundToWeek(stat); 
map.insert(key, stat); 

И вам должно быть хорошо.

2

Спасибо за ваши ответы.

Я собираюсь пойти с NavigableMap, так как функция floorKey - это именно то, что мне нужно.

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