#java
#java
Вопрос:
У меня есть два класса, представляющие сегменты путешествия — класс сегмента и класс лагеря. Технически Camp является типом сегмента, но на данный момент я не могу изменить дизайн объекта, поэтому предположим, что они не связаны. Оба сегмента и лагеря содержат поля даты проверки и проверки.
Что мне нужно сделать, это перебрать список сегментов и список лагерей и вызвать определенную функцию для каждого из сегментов и лагерей в этих списках. Однако функция должна вызываться в последовательном порядке дат для каждого из сегментов и лагерей.
Очевидно, что я могу сортировать списки сегментов и лагерей отдельно, но проблема возникает, если есть лагерь, для которого функция должна вызываться между сегментами.
Так, например, если у меня есть следующее:
Список сегментов
Сегмент 1 — 16.10.14
Сегмент 2 — 24.10.14
Список лагерей
Лагерь 1 — 17.10.14
Лагерь 2 — 18.10.14
Мне нужно было бы выполнить операцию с сегментами / лагерями в следующем порядке:
Сегмент 1
Лагерь 1
Лагерь 2
Сегмент 2
На мой взгляд, у меня есть несколько вариантов решения этой проблемы, но мне интересно, какой наиболее эффективный / лучший способ сделать это. Я мог бы создать некоторый вспомогательный класс, содержащий поля как сегментов, так и лагерей, и создать список объектов этого вспомогательного класса, который содержит либо сведения о сегментах, либо сведения о лагерях.
Это то, что у меня есть в настоящее время. Я решил использовать картографический подход к сопоставлению дат с лагерями, поэтому я перебираю ключи карты (даты) и смотрю, предшествует ли какая-либо из этих дат дате сегмента, и если да, выполняю операцию над ними. Есть ли лучший способ сделать это? Мне это кажется уродливым и запутанным.
final Map<Date, List<Camp>> campMap = new HashMap();
for (Camp camp : pnr.getCamps()) {
if (campMap.get(camp.getCheckInDate()) == null) {
final List<Camp> camps = new ArrayList<Camp>();
camps.add(camp);
campMap.put(camp.getCheckInDate(), camps);
} else {
campMap.get(camp.getCheckInDate()).add(camp);
}
}
final List<Date> datesToDelete = new ArrayList<Date>();
for (Segment segment : pnr.getSegments()) {
// here is where I loop through the segments to perform an operation on each of them
for (Map.Entry<Date, List<Camp>> entry : campMap.entrySet()) {
if (entry.getKey().before(segment.getSegmentDate())
|| entry.getKey().equals(segment.getSegmentDate())) {
for (Camp camp : entry.getValue()) {
// do something with the camp
}
datesToDelete.add(entry.getKey());
}
}
for (Date date : datesToDelete) {
campMap.remove(date);
}
datesToDelete.clear();
// do something with the segment
}
По сути, я спрашиваю, есть ли лучший / более интуитивно понятный / более чистый способ сделать это. Большое спасибо за любую помощь.
Комментарии:
1. Можете ли вы изменить источник сегментов и лагерей? т.Е. заставить их реализовать общий интерфейс?
2. Да, я мог бы заставить их реализовать общий интерфейс в исходном коде Java — единственное, что я не могу изменить, это модель данных — ie. объекты БД, поэтому я не могу, например, расширить сегмент Camp.
Ответ №1:
Нет «правильного» способа решения этой проблемы; но для меня я бы хотел, чтобы ваши классы реализовали общий интерфейс, что-то вроде:
public interface DateAware {
long getDate();
}
После того, как вы это сделаете, вы можете начать работать с ними полиморфно. Вы могли бы, например, использовать простой компаратор для их сортировки с помощью Collections.sort
:
public class DateAwareComparator implements Comparator<DateAware> {
int compare(DateAware o1, DateAware o2) {
return Long.compare(o1.getDate(), o2.getDate());
}
}
И теперь вы можете делать такие вещи, как:
List<DateAware> list = new ArrayList<>();
list.addAll(segments);
list.addAll(camps);
Использование интерфейса также имеет то преимущество, что вы не накладываете никаких ограничений на иерархию наследования для достижения того, что вам нужно.
Комментарии:
1. Код неполный, но это правильный путь. Есть пользовательский компаратор, который может сравнивать два сегмента, два лагеря или микс, сравнивая даты
Collections.sort(segmentAndCampList, new SegmentAndCampComparator())
2. Для предоставленного кода от автора этого решения более достаточно. Автору просто нужно убедиться, что оба его класса реализуют интерфейс, в данном случае это означает замену обоих методов
getCheckInDate
иgetSegmentDate
общим методом в интерфейсе.
Ответ №2:
Есть пользовательский Comparator
(http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html ), который может сравнить два сегмента, два лагеря или их сочетание, сравнивая даты, а затем Collections.sort(segmentAndCampList, new SegmentAndCampComparator())