I have two classes:
Class Node {
int address
}
Class Link{
int latency;
int bandwidth;
Node node1;
Node node2;
}
public Link [] link= new Link[Nmax];
if I want to create a link between two nodes, it is easy, I've just to:
node1=new Node(); //and then I add parameter like address and so on
node2= new Node();//...............
link[1]= new Link();
link[1].node1=node1;
link[1].node2=node2;
link[1].latency=15; //and so on, we suppose that we have 100 nodes and 60 links
Now, during the program, sometimes we add some new nodes then we have to add links between them, I can do this with the same manner us above, my question is:
what I have to do if I want to delete a node ? (links between this node and other existing nodes must be deleted too)
--- Edited in response to jpm's excellent observation ---
In your case, you are doing all of the data structure management yourself, but are not storing enough infomation to undo the additions to the data structure.
You need to store enough information at create time to support the other operations on the data structure. This means that perhaps the choice of an array as your high-level exposed data structure is a bad choice, because there is no guarantee that additions will maintain the sufficient information to support the removals.
Wrap the array in an object, and write the code in the add(...) method to support the efficient removal. This probably means storing more information, which was constructed specifically for the support of removal.
--- Original post follows ---
To delete an object in Java, ensure that nothing "points" to it (has a reference to it) and then wait. Automatic garbage collection will do the deleting for you.
An example to make this clear
link[1] = new Link();
// now we have an extra Link in our array
link[1] = null;
// now garbage collection will delete the recently added Link object.
Note that if you have two or three references to the created Link object, it will not be collected until all the references are lost
link[1] = new Link();
// now we have an extra Link in our array
Link current = link[1];
// now we have two references to the newly created Link
link[1] = null;
// now we have one reference to the newly created Link
current = null;
// now the newly created Link is a candidate for garbage collection
The way this is implemented is there is a top-level Thread of the user implemented program. If that thread can reach the Object in question then it won't get garbage collected. This means that rings and meshes of Objects that are no longer reachable from the live Threads will be collected in mass.
before deleting a node; loop over your links and remove any that have your node to be deleted as node1 or node2, then delete your node.
You probably want to explore using a better data structure than an array for this use case. You want to be able to inspect all Links, figure out which ones refer to the deleted Node, and remove those Links. Start looking at List/Set and see if they suit your needs, and slowly evolve into a good implementation that gives you what you need.
"Deleting" an object in Java means to remove all references that point to the object. The Garbage Collector then eventually will free the memory occupied by the object. So what you need to do, would be to set all references to a specific Node object to null.
// lets delete node1
link[1].node1 = null;
node1 = null;
// at some point the object will be deleted
Related
I went to interview today and this question got thrown at me. I can't come up with an answer.
the gig is
SList2 = SList1.clone();
if you change things in SList1 (e.g editing the object) it will not affect the similar object in SList2. I attempt it, I create new nodes but whenever I get to the cloning object part I failed. Was thinking about object.clone() but the question state that no built-in function is allowed.
Slist2.head = new Node();
Node newList = Slist2.head;
Node head = Slist1.head;
Slist.head.(all data) = head.(all data);
while(head.hasNext()){
head = head.next();
Node newGuy = newNode();
newNode.(all data) = node.(all data)
newList.next = newGuy;
}
This will follow through the old list, manually copying all data into a new node and tacking that node on to the new list
This is two problems disguised as one.
How would I read in the values from the linked list object, and
How would I create it in such a way that no references were reused (that is, I don't just reassign the head of one list to the head of the other)?
Without diving into code, let's look at this at a high level. Provided that your linked list can provide iteration (that is, it has an Iterator-like object that keeps its state in the list, and returns a node when next() is referenced), then the first problem becomes a matter of iterating over the linked list via the iterator.
From there, you would want to peel out the raw value from what you're iterating over, and add them into your new linked list object.
You're pretty much done then; nothing fancy needs to be worked out. It's literally taking data from one structure and inserting it into another.
I need help with something. my code is of the following template.
Assume customObject has multiple property1, property2, ..property100.
List<CustomObject> customObjectList = /*<method call to external API that returns the said list >*/
if(customObjectList != null && customObjectList.size() > 0){
//*** point A ***<clone the Object>
resultList = <some method that process the above list>(customObjectList)
if(resultList.size() > 0){
for(Iterator<Map.Entry<CustomObject, ExternalResponse>> itr = resultList.entrySet().iterator(); itr.hasNext();) {
//code that modifies the properties in the CustomObjects
//*** point B ***resetAProperty(<Object clone>)
}
}
}
At point B, I need the one unmodified specific property of original object to use in the method. I have two strategies for this:
Clone the object at point A, and use the cloned copy to get the
property as shown in above code. At point A, Use a for loop and a
Map to form an associate array of object names, property original
values and traverse them to get the property initial value at point
B
Avoid Cloning because it always requires Deep Cloning
.clone() especially on a List will almost always end in tears because you would have to deep clone all the objects in the list, all their referenced objects, and so on.
Deep Cloning means you have to make a binary copy of every last object in the Object graph. Just copying a reference will give you a shallow copy and you will see any changes that are made to the referenced object. Just miss one property and you will have a hell of a time finding that bug.
Solution
What you should do is make all your CustomObject instances Immutable and then you don't need to worry about versioning, they can never change, mutation would involve creating a new instance that is also Immutable and a complete different object. Then you never had to worry about versions.
Of course all the instance variables that point to other objects will need to be Immutable as well. This is the same problem as the deep clone but taking from another angle. A much more manageable angle.
Cat------>Dog------>Horse----->Parrot
^P1 ^P2 ^P3 ^P4
Draw the resulting linked list after executing the following statements:
P4 = P2;
P3.info = P2.info
etc.
My question is, what does '.info' reference?
I've looked in the API for both node and linked list and haven't found anything.
Any ideas?
This would entirely depend on the specific implementation used in your assignment, but it sounds like info contains the data of the specific node in the linked list, i.e. P1.info is Cat.
Each node in a standard linked list has two pieces of information:
A reference the the next node
The data contained in the current node
I'm not sure if your instructor wants you to take into account that you would have to "clone" the node in order to have a separate object with the same data or if your instructor wants you to take it literally where setting one object equal to another object simply makes the first one a reference to the second one.
As spookyjon said, the info appears to be a public variable in the node class for the data (cat, dog, horse, parrot).
I have a custom DefaultMutableTreeNode class that is designed to support robust connections between many types of data attributes (for me those attributes could be strings, user-defined tags, or timestamps).
As I aggregate data, I'd like to give the user a live preview of the stored data we've seen so far. For efficiency reasons, I'd like to only keep one copy of a particular attribute, that may have many connections to other attributes.
Example: The user-defined tag "LOL" occurs at five different times (represented by TimeStamps). So my JTree (the class that is displaying this information) will have five parent nodes (one for each time that tag occured). Those parent nodes should ALL SHARE ONE INSTANCE of the DefaultMutableTreeNode defined for the "LOL" tag.
Unfortunately, using the add(MutableTreeNode newChild) REMOVES newChild from WHATEVER the current parent node is. That's really too bad, since I want ALL of the parent nodes to have THE SAME child node.
Here is a picture of DOING IT WRONG (Curtis is the author and he should appear FOR ALL THE SHOWS):
How can I accomplish this easily in Java?
Update
I've been looking at the code for DefaultMutableTreeNode.add()... and I'm surprised it works the way it does (comments are mine):
public void add(MutableTreeNode child)
{
if (! allowsChildren)
throw new IllegalStateException();
if (child == null)
throw new IllegalArgumentException();
if (isNodeAncestor(child))
throw new IllegalArgumentException("Cannot add ancestor node.");
// one of these two lines contains the magic that prevents a single "pointer" from being
// a child within MANY DefaultMutableTreeNode Vector<MutableTreeNode> children arrays...
children.add(child); // just adds a pointer to the child to the Vector array?
child.setParent(this); // this just sets the parent for this particular instance
}
If you want easily, you should probably give up on sharing the actual TreeNodes themselves. The whole model is built on the assumption that each node has only one parent. I'd focus instead on designing your custom TreeNode so that multiple nodes can all read their data from the same place, thereby keeping them synced.
I'm not sure it qualifies as easy, but you might look at Creating a Data Model by implementing TreeModel, which "does not require that nodes be represented by DefaultMutableTreeNode objects, or even that nodes implement the TreeNode interface." In addition to the tutorial example, there's a file system example cited here.
Unfortunately, I believe the answer is no. In order to do what you're talking about, you would need to have DefaultMutableTreeNode's internal userObject be a pointer to some String, so that all the corresponding DefaultMutableTreeNode's could point to and share the same String object.
However, you can't call DefaultMutableTreeNode.setUserObject() with any such String pointer, because Java does not have such a concept on the level that C or C++ does. Check out this outstanding blog article on the confusing misconceptions about pass-by-value and pass-by-reference in Java.
Update: Responding to your comment here in the answer space, so I can include a code example. Yes, it's true that Java works with pointers internally... and sometimes you have to clone an object reference to avoid unwanted changes to the original. However, to make a long story short (read the blog article above), this isn't one of those occasions.
public static void main(String[] args) {
// This HashMap is a simplification of your hypothetical collection of values,
// shared by all DefaultMutableTreeNode's
HashMap<String, String> masterObjectCollection = new HashMap<String, String>();
masterObjectCollection.put("testString", "The original string");
// Here's a simplification of some other method elsewhere making changes to
// an object in the master collection
modifyString(masterObjectCollection.get("testString"));
// You're still going to see the original String printed. When you called
// that method, a reference to you object was passed by value... the ultimate
// result being that the original object in you master collection does
// not get changed based on what happens in that other method.
System.out.println(masterObjectCollection.get("testString"));
}
private static void modifyString(String theString) {
theString += "... with its value modified";
}
You might want to check out the JIDE Swing extensions, of which some components are commercial while others are open source and free as in beer. You might find some kind of component that comes closer to accomplishing exactly what you want.
If I have a linked list structure, and I implement the clear() method as follows:
public void clear() {
firstNode = null;
size = 0;
}
will it still get correctly garbage collected, or would I want to walk through each node, setting nextNode to null?
None of the nodes can be directly referenced from outside the linked list, so there's no case where there would be a reference to any of them outside my class, but I'm unsure if Java would correctly garbage collect the remaining chained nodes.
That should be fine - Java handles cyclic references etc with no problems.
Since none of the nodes of the list have external references. Setting firstNode to null will make all the nodes eligible for GC as there would be no way to reach any of the nodes from an external reference.
for your information, the LinkedList implementation by Sun parse all elements of the list and set them to null