#java #mysql #jung
#java #mysql #юнг
Вопрос:
У меня есть результирующий набор, поступающий из базы данных mysql, и я пытаюсь построить график ЮНГА, используя эти значения. Я уже создал экземпляр своего пустого графика как:
Graph<Node, Edge> g = new SparseMultigraph<>();
затем я добавил узлы (586). Сейчас я нахожусь в процессе добавления ссылок, и теперь все становится еще сложнее. Структура моего пользовательского ребра очень проста, у него просто есть свойство «time», например:
Multiset<Timestamp> time;
Результирующий набор для ссылок содержит 3273684 записи в форме:
id time sender receiver
12 2014-03-20 09:26:04.000 2 99
Теперь, что я хочу сделать, это создать ссылку из узла с идентификатором 2 и узла с идентификатором 99, если ссылка не существует, или просто добавить временную метку к уже существующей ссылке. Что я делаю, так это:
while (resultSet.next()) {
// retrieve sender
Node sender = findNode(resultSet.getInt("sender"), g);
// retrieve receiver
Node receiver = findNode(resultSet.getInt("receiver"), g);
// if they are already linked
if(g.isPredecessor(sender, receiver)){
// just add the new timestamp to the existing link
Collection<Edge> outEdges = g.getOutEdges(sender);
// find the right edge
for(Edge e:outEdges){
// if this edge is connected to receiver
if(g.getDest(e).equals(receiver)){
// add the new timestamp to this edge
e.setTime(resultSet.getTimestamp("time"));
}
}
} else { // else a new link is added
Information e = new Information();
e.setId(resultSet.getInt("id"));
e.setTime(resultSet.getTimestamp("time"));
g.addEdge(e, sender, receiver, EdgeType.DIRECTED);
}
}
Моя проблема в том, что это действительно медленно, и я не понимаю, нормально ли это, поскольку результирующий набор довольно большой, или мне не хватает более четкого / быстрого способа реализовать то, что мне нужно.
Для наглядности мой метод findNode() выглядит следующим образом:
private static Node findNode(int aInt, Graph<Node, Edge>g) {
for(Node n:g.getVertices()){
if(n.getId()== aInt){
return n;
}
}
return null;
}
Ответ №1:
Это происходит медленно по двум причинам:
(1) У вас нет эффективного способа поиска узла с заданным идентификатором. Для графика такого размера я бы рекомендовал создавать карту по мере заполнения графика и использовать эту карту для реализации findNode() .
(2) Если у вас есть два узла и вы хотите получить ребро, которое их соединяет (если таковое имеется), просто используйте Graph.findEdge() .
(1) на сегодняшний день является основной причиной того, что ваш код работает медленно. (2) не так сильно поможет, но это также сделает ваш код более удобным для чтения и более элегантным.
Комментарии:
1. Пример, нет. По сути, когда вы строите свой график, в какой-то момент вы только что построили свой объект node, и поэтому у вас будет под рукой узел и его идентификатор; поместите их на карту в этот момент. Навскидку самый простой способ сделать это, вероятно, состоял бы в том, чтобы в вашем классе node был экземпляр статической карты внутри него. Это также означало бы, что сам findNode() должен быть статическим методом вашего класса node.
2. Спасибо, Джошуа, я выбрал hashmap<целое число, узел>, где я помещаю идентификатор и узел непосредственно перед добавлением узла в график … на данный момент мне больше не нужен метод findNode(), это просто get() из хэш-карты, когда мне нужнонайдите правильный узел… Это несколько близко к тому, что вы имели в виду в своем ответе?
3. и, кстати, у меня проблемы с Graph.findEdge() … вы видите, я проверяю g.isPredecessor(отправитель, получатель), но если это правда, и я прошу g.findEdge(отправитель, получатель) Я получаю исключение нулевого указателя…
4. Simone@ проблема с findEdge () звучит как другая проблема. 🙂 Пожалуйста, опубликуйте его как отдельный вопрос с трассировкой стека и небольшим автономным примером, который его демонстрирует.
5. Симона @, я не могу сказать наверняка из вашего описания, но похоже, что ваше решение для Map<> по сути является тем, что я описал.