Java TreeNode: How to prevent getChildCount from doing expensive operation? - java

I'm writing a Java Tree in which tree nodes could have children that take a long time to compute (in this case, it's a file system, where there may be network timeouts that prevent getting a list of files from an attached drive).
The problem I'm finding is this:
getChildCount() is called before the user specifically requests opening a particular branch of the tree. I believe this is done so the JTree knows whether to show a + icon next to the node.
An accurate count of children from getChildCount() would need to perform the potentially expensive operation
If I fake the value of getChildCount(), the tree only allocates space for that many child nodes before asking for an enumeration of the children. (If I return '1', I'll only see 1 child listed, despite that there are more)
The enumeration of the children can be expensive and time-consuming, I'm okay with that. But I'm not okay with getChildCount() needing to know the exact number of children.
Any way I can work around this?
Added: The other problem is that if one of the nodes represents a floppy drive (how archaic!), the drive will be polled before the user asks for its files; if there's no disk in the drive, this results in a system error.
Update: Unfortunately, implementing the TreeWillExpand listener isn't the solution. That can allow you to veto an expansion, but the number of nodes shown is still restricted by the value returned by TreeNode.getChildCount().

http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html#data
scroll a little down, there is the exact tutorial on how to create lazy loading nodes for the jtree, complete with examples and documentation

I'm not sure if it's entirely applicable, but I recently worked around problems with a slow tree by pre-computing the answers to methods that would normally require going through the list of children. I only recompute them when children are added or removed or updated. In my case, some of the methods would have had to go recursively down the tree to figure out things like 'how many bytes are stored' for each node.

If you need a lot of access to a particular feature of your data structure that is expensive to compute, it may make sense to pre-compute it.
In the case of TreeNodes, this means that your TreeNodes would have to store their Child count. To explain it a bit more in detail: when you create a node n0 this node has a childcount (cc) of 0. When you add a node n1 as a child of this one, you n1.cc + cc++.
The tricky bit is the remove operation. You have to keep backlinks to parents and go up the hierarchy to subtract the cc of your current node.
In case you just want to have the a hasChildren feature for your nodes or override getChildCount, a boolean might be enough and would not force you to go up the whole hierarchy in case of removal. Or you could remove the backlinks and just say that you lose precision on remove operations. The TreeNode interface actually doesn't force you to provide a remove operation, but you probably want one anyway.
Well, that's the deal. In order to come up with precomputed precise values, you will have to keep backlinks of some sorts. If you don't you'd better call your method hasHadChildren or the more amusing isVirgin.

There are a few parts to the solution:
Like Lorenzo Boccaccia said, use the TreeWillExpandListener
Also, need to call nodesWereInserted on the tree, so the proper number of nodes will be displayed. See this code
I have determined that if you don't know the child count, TreeNode.getChildCount() needs to return at least 1 (it can't return 0)

Related

Count number of agents at a node

I have set up a polygonal node (called area_wait) that a single type of agent remain at whilst in a queue. I'm trying to find the number of agents at a node using a function. I don't want to count the agents in the queue as I have set up one queue for all waiting agents which might be at different nodes.
I'm using the following code which always returns zero.
int count_X = area_wait.agents().size();
In fact the list is empty when I check with:
List list_X = area_wait.agents();
What am I doing wrong? Thanks in advance.
I will give you the same answer I gave in the anylogic users group which can be found here: https://www.linkedin.com/feed/update/urn:li:activity:6721800348408791040
so this function you are trying to use doesn't work... unless the thing that is inside the node is a transporter and only if the node has a speed or access restriction... this might either be a bug or something explained poorly on the documentation, but it sounds like a bug to me
If you want to know the number of agents in a node you can use the alternative method count(myAgents,a->a.getNetworkNode()!=null && a.getNetworkNode().equals(yourNode)) but this fails if you change the node position without a moveTo block or some other natural movement (such as defining your node in the agent location parameter of a block)... so.. that's another bug, but maybe it won't apply to you
So summary... no easy and safe solution as far as I know

Reducing tree of attributes

I have a tree of several thousand nodes, decorated by boolean attributes, something like this (attributes in parentheses):
Root (x=true, y=true, z=false)
Interior 1
Leaf 1 (x=false, z=false)
Leaf 2 (x=false, y=false, z=false)
Interior 2
Leaf 3
etc.
What I would like to do is find the smallest number of decorations necessary to preserve the values of the attributes, given the following constraints/info:
Attributes are inherited by child nodes
Only the resulting attributes of the leaf nodes are important (including inherited attributes). So if setting a "default" attribute on an interior node lets me drop a bunch of attributes on its children, that's okay.
There is a shorthand in our model for setting all attributes to either true or false. For example, (x=false,y=false,z=false) can be represented by one decorator, whereas (x=false,y=false,z=true) would take three.
The number of child nodes will greatly outnumber the interior nodes (at least 25 to 1)
The initial state of the tree will have many redundancies.
I'm using Java and adding an external lib to deal with this isn't a big deal.
These constraints are not flexible as I'm working on an integration layer with a Large Enterprise System, so all I can do is try to minimize the number of attribute values we have to store and transit.
I think constraint #3 is throwing me for a loop, because without it I could just deal with each attribute individually, which is simple (and I already implemented a solution to that before I realized more attributes were coming).
I hope this is descriptive enough to give a picture of the general problem. I can give more examples or information if required. Thank you!
I think (3.) can be mainly ignored because we'd only be interested in it for leaves.
Here's what I would suggest:
for every leaf with all booleans one way, use the shortcut (3.).
Then for every internal node, assign attributes to the majority value for leaves below, not handled by 1, and remove the now redundant assignments.
For higher internal nodes, do the same, looking at immediate children, up to the root.
This is a heuristic, and I haven't tried it, but would be my first shot if I were you.
Let me know how it goes.

Given a large tree structure, is there an efficient algorithm to do querying or filtering on the tree?

Let's say I wanted all nodes whose parent(s) matched some certain condition.
Is there an accepted way of doing this other than inspecting each node and building a results object full of either nodes or subtrees?
If the tree is not in already sorted or indexed based on the search condition in some way, then you cannot prune the tree traversal (i.e. you cannot decide to not take the right child at some particular node, for instance). Therefore, you have no choice but to traverse the entire tree.
That's pretty much it. You simply have to access each node to see whether it matches the criteria.
But there are some ways to speed it up:
Use an index. If you are repeatedly querying the same property, it might be beneficial to create an index on that property and use for searching. This could speed up your code immensely. Doing is not free though: you need to calculate the index up front, update it every time you update the tree and you need more memory to keep it.
If you have a multi-core machine, you can process individual subtrees in parallel by using separate threads.

What is the most efficent way to create a tree in java?

I am creating a tree in java to model the Extensive-form of a game for an AI. The tree will be an 25-ary tree (a tree in which each branch at most has 25 child branches) because at each turn of the game there are 25 different moves. Because the number of new branches that have to be created in each new layer of the tree is 25^n I'm very concerned with making this efficient. (I intend to remorselessly cut of branches to keep them from growing in order to keep things from getting bogged down). What is the best way to model such a tree when efficiency is such a concern? My first impression is to have a node object where each node has a parent node and an array of child nodes but this means creating a lot of objects. Ultimately these are my questions:
Is this the fastest way create and manage my tree?
What is a good way to figure out how much time any given algorithm or process in a program is going to take? (the only one I've thought of so far is to create a date before the process and then after and compare the # of milliseconds that have passed)
Any other thoughts are also welcome. My question implies and is related to a great number of other questions, i would expect. If i have been ambiguous or unclear please comment to let me know instead of down-voting and storming off as this isn't productive.
Realistically, the way you described is the best approach. It'll perform reasonably well compared to anything else you could do and will be straightforward to implement.
Time and again people are asking questions about how to do something "efficiently". The best answer is nearly always, "don't even bother trying". Unless your improvement is an algorithmic one, it's unlikely to make much difference anyway, and especially in a case like this, the extra effort and complexity isn't worth whatever miniscule gain you might be able to achieve.
Putting it another way, and to borrow a quote (though I can't remember the originator), the first rule of optimization is: don't.
Having said that, if you really feel the need to squeeze every last drop of speed, you could try caching and re-using objects (instead of discarding them completely, keep track of them in a free object store, and then when you need to create a new object, first check the free object store to check if there is an existing one). As always, you'll need to measure performance before and after to see if it really helps (chances are it won't help much, unless physical memory is really constrained, in which case garbage collection can become expensive).
I agree with the previous comment about only optimizing once you have implemented the rest of the application.
On the other hand, I do realize a few things that may be of importance:
Branching factor of 25: Although not ridiculously huge, it is still large with respect to other problems. For a tree, you will definitely have to have a list for each node to indicate the list of SubNodes. You can do this either by making a Node class which has a collection of nodes within it, or have an external Map that maps a given node to a list of children nodes.
Removing and adding of elements will be done: This lends itself to a LinkedList implementation of the stored children since you don't want to perform costly removes and adds. A HashSet may work also, but the problem is that you may need more memory.
Iteration of the elements may or may not be done: If you want to iterate over the entire list at each step, LinkedLists are fine. If you want to prioritize the nodes then you may be saving memory by using a priority queue data structure. Priority queues are especially helpful if you are going to implement a heuristic function and evaluate which child to move to at any given node.
Thats all I have so far, but I'll keep updating if I think of more things, or if you update your content.

ROLLBACK undo redo

I'm building a database using a BST (binary search tree) and I want the user to be able to roll back the last 5 commands. Any Suggestions? I'm using Java.
Have you considered using Berkey DB? It's free and supported nested transactions (which would allow you to have any number of levels of rollback):
http://download.oracle.com/docs/cd/E17076_02/html/gsg_txn/JAVA/nestedtxn.html
Even if you decide to implement your own DB, it might be useful as a reference.
It sounds like you want the Memento pattern. Essentially, you create an object that has all of the information required to:
From the state of the tree before the operation, repeat the operation. (Redo)
From the state of the tree after the operation, revert the operation. (Undo)
You'd keep the last five of these around. When the user asks for an undo, take the latest, ask it to revert the operation, then indicate somehow (some index variable, for example) where you are in the list of mementos. You should then be able to move through the list in either direction, undoing and redoing as much as you want.

Categories