Java TreeNode: как предотвратить дорогостоящую операцию getChildCount?

Я пишу дерево Java, в котором узлы дерева могут иметь дочерние элементы, для вычисления которых требуется много времени (в данном случае это файловая система, где могут быть сетевые тайм-ауты, препятствующие получению списка файлов с подключенного диска).

Проблема, которую я нахожу, заключается в следующем:

  1. getChildCount() вызывается перед тем, как пользователь специально запрашивает открытие определенной ветви дерева. Я считаю, что это сделано для того, чтобы JTree знал, показывать ли значок + рядом с узлом.

  2. Для выполнения потенциально дорогостоящей операции потребуется точный подсчет детей из getChildCount().

  3. Если я подделываю значение getChildCount(), дерево выделяет место только для этого количества дочерних узлов, прежде чем запрашивать перечисление дочерних узлов. (Если я верну «1», я увижу только 1 ребенка в списке, несмотря на то, что их больше)

Подсчет детей может быть дорогим и трудоемким, я согласен с этим. Но я не согласен с тем, что getChildCount() нужно знать точное количество детей.

Как я могу обойти это?

Добавлено: Другая проблема заключается в том, что если один из узлов представляет дисковод для гибких дисков (как это архаично!), дисковод будет опрошен до того, как пользователь запросит его файлы; если в приводе нет диска, это приводит к системной ошибке.

Обновление: К сожалению, реализация прослушивателя TreeWillExpand не является решением. Это может позволить вам наложить вето на расширение, но количество отображаемых узлов по-прежнему ограничено значением, возвращаемым TreeNode.getChildCount().


person David Koelle    schedule 30.09.2008    source источник


Ответы (4)


http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html#data

прокрутите немного вниз, там есть точное руководство по созданию узлов ленивой загрузки для jtree с примерами и документацией

person Lorenzo Boccaccia    schedule 30.09.2008

Я не уверен, что это полностью применимо, но недавно я работал над проблемами с медленным деревом, предварительно вычисляя ответы для методов, которые обычно требуют просмотра списка дочерних элементов. Я пересчитываю их только тогда, когда дети добавляются, удаляются или обновляются. В моем случае некоторым методам пришлось бы рекурсивно спускаться по дереву, чтобы выяснить такие вещи, как «сколько байтов хранится» для каждого узла.

person Paul Tomblin    schedule 30.09.2008

Если вам нужен большой доступ к определенной функции вашей структуры данных, которая требует больших затрат для вычислений, может иметь смысл предварительно вычислить ее.

В случае TreeNodes это означает, что ваши TreeNodes должны будут хранить количество дочерних элементов. Чтобы объяснить это немного подробнее: когда вы создаете узел n0, этот узел имеет число дочерних элементов (cc), равное 0. Когда вы добавляете узел n1 в качестве дочернего по отношению к этому, вы n1.cc + cc++.

Хитрый бит - это операция удаления. Вы должны сохранить обратные ссылки на родителей и подняться вверх по иерархии, чтобы вычесть cc вашего текущего узла.

В случае, если вы просто хотите иметь функцию hasChildren для своих узлов или переопределить getChildCount, может быть достаточно логического значения, которое не заставит вас подниматься по всей иерархии в случае удаления. Или вы можете удалить обратные ссылки и просто сказать, что теряете точность операций удаления. Интерфейс TreeNode на самом деле не требует от вас предоставления операции удаления, но вы, вероятно, все равно захотите ее.

Ну, это сделка. Чтобы получить заранее вычисленные точные значения, вам нужно будет сохранить некоторые виды обратных ссылок. Если нет, лучше назовите свой метод hasHadChildren или, что более забавно, isVirgin.

person Aleksandar Dimitrov    schedule 30.09.2008

Есть несколько частей решения:

  • Как сказал Лоренцо Боккачча, используйте TreeWillExpandListener.

  • Также необходимо вызвать nodesWereInserted для дерева, чтобы отображалось правильное количество узлов. Посмотрите этот код

  • Я определил, что если вы не знаете количество дочерних элементов, TreeNode.getChildCount() должен возвращать как минимум 1 (он не может возвращать 0)

person David Koelle    schedule 01.10.2008