How to create a root node in a linked list? - java

I'm trying to learn linked-lists in Java and had some questions about the code below:
public class List {
Node root;
public List() {
// constructor
}
public int pop() {
// pop logic
}
public int push(int data) {
// push logic
}
}
I'd like to have a List class for popping and pushing data into the linked list. However, since the list won't have any default data on instantiation, what would be the best way for storing a reference to the root node?
In C, I would just have a pointer like:
Node * root;
But since Java does not have pointer, would having a simple declaration like:
Node root;
... be acceptable? I haven't used Java in a while, but doesn't allocating memory to an object declared as a class variable cause potential memory issues? Thanks!

Yes, a simple declaration like Node root is acceptable. It is not actually a pointer, but a reference that can potentially refer to any Node.
References in Java are conceptually equivalent to C pointers, but are less flexible and use a simpler syntax.

Yes,
Node root;
Is acceptable. Every non-primitive object (including arrays of primitives or objects) in Java is actually a reference to an object, so it is like a C pointer in many ways.
It is actually so much like a pointer, that this declaration by itself isn't actually creating an object. It is a reference that is not pointing to anything yet, and if you try to use root before assigning it to a new Node() first, you will get a NullPointerException.

Yes, Node root; is absolutely fine. Just make sure you don't change the value of root. For using it, create another variable, for traversing a path: Node start = root; This way root remains untouched.
I haven't used Java in a while, but doesn't allocating memory to an object declared as a class variable cause potential memory issues?
No it doesn't. While simply writing Node root; doesn't allocate any memory, root = new Node(); does. Take a note here that class members in java are static, the non-static members are global variables. Allocating memory to global variables in java is a common practice. For example, the variable where you actually store the list, will be a global variable, and you will have to allocate memory to it.
Java has a robust memory management system, so you won't run into memory issues too easily.

Related

Java Recursion - Alternative to passing-by-reference:

I'm migrating from C to Java and I'm having difficulties with recursion, specially because in Java you can't pass an argument by reference.
What I'm looking is not a solution/trick to force Java pass an argument by reference, but the recommended way to solve such a problem in Java.
Let's take the recursive node insertion in a binary tree:
void nodeInsert(Node n, int a) {
if (n == null)
n = new Node(a);
...
}
In C, by the end of the execution, the node n in the tree would point to the newly created node. In Java, however, n will still be null (because n is passed by value).
What is the suggested Java approach for such problems?
Some approaches I already tried:
Using a static object to keep track of the parent (issue complicates when using generics).
Passing the parent node as part of the function. It works but complicates the code a bit and doesn't look as a good solution.
Creating an additional member pointing to the parent node but this is not a good solution, as it increases the space required by O(n);
Any advice is welcome.
In Java instead of using reference variables, we use return values and assign it to the variable that has to be changed.
Node nodeInsert(Node n, int a) {
if (n == null){
n = new Node(a);
return n;
}
else
{
....
return nodeInsert(n,a); //this is how a recursion is done.
....
}
}
If you need more on recursion http://www.toves.org/books/java/ch18-recurex/ will teach you right.
A common way to implement is to maintain the node relationships inside the node itself. Quite a lot of examples can be found in implementations of various JDK datastructures. So the Node is the container for the value and contains references to other nodes, depending on the data structure.
If you need a child->parent relationship between nodes, the Node class would look like
class Node<T> {
T value;
Node parent;
}
In case of insert, you create a new node, set the parent reference to the original one, and return the new Node as a result (this is optional, but not uncommon to do, so the call has a handle of the new child)
Node<T> insert(Node<T> parent, T value) {
Node<T> child = new Node<>();
child.value = value;
child.parent = parent;
return child;
}
And yes, this adds a minor overhead of 4 bytes per Node (or 8 bytes, on 64bit JVMs without compressed pointers)
I propose the following solutions:
Implement a method in class Node that adds a child node. This makes use of the OO-possibility to encapsulate data and functionality together in a class.
Change nodeInsert to return the new node and add it to the parent in the caller (also mentioned in comments). The responsibility of nodeInsert is to create the node. This is a clear responsibility and the method signature shows what the result of the method is. If the creation is not more than new Node() it might not be worth to have a separate method for it.
You can pass a holder object that in turn references your new Node object
void nodeInsert(AtomicReference<Node> r, int a) {
if (r.get() == null)
r.set(new Node(a));
...
}
Or you could pass an array with space for one element.
After months posting this question, I realized yet another solution that is, in fact, already contemplated in java design patterns but not mentioned here: Null Object Pattern.
The downside is that each null occupies memory (in some cases, like large Red-Black trees, this could become significant).

I'm going from learning C/C++ to learning Java: What the heck is this?

I just saw an implementation of a linked list in Java (http://www.danielacton.com/Data-Structures/Linked-List/Java/), and here's what a node looked like:
private class ListNode {
private Object data;
private ListNode next;
}
What the heck is that????
The size of a ListNode must be infinity bytes, if you think about the logic here. Shouldn't the ListNode hold the address of another ListNode?
That's one of the confusing things about going from C++ to Java. In Java,
private ListNode next;
declares a reference variable, most closely compared to a ListNode& reference in C++. This is one way of creating a linked list in Java - have a node store the data and the reference to the next item.
Note that in Java, the default value (if uninitialized) of next would be null.
For this to take blow up the way you think, it would have to be:
private ListNode next = new ListNode();
which would eventually result in a StackOverflowError.
The default value of the variable ListNode next; is null, meaning it does not actually point to a ListNode Object until you assign one to the variable. So no - there is no infinite loop.
When you:
X whatever;
where X is a class, whatever is a reference, not a full object. This is unlike C and C++ where you can have full structs on the stack.
Although this is not technically exact, you can see them as C/C++ pointers. Except that you use dot for "indirections".

Keeping the address space the same in java

I'm trying to keep my address the same, since I have a JList pointing towards listAccts. How do I make ListAccts have the same address space? Basically, how do I copy this object?
public class BankEngine extends AbstractListModel {
/** holds the accounts inside the bank engine */
private ArrayList<Account> listAccts;
/** holds all the actions the user has done. */
private ArrayList<Action> actions;
/** holds old versions of the bank. */
private ArrayList<ArrayList<Account>> oldEngines;
/*****************************************************************
* Constructor that creates a new BankEngine, the core of the project
******************************************************************/
public BankEngine() {
listAccts = new ArrayList<Account>();
// actions = new ArrayList<Action>();
oldEngines = new ArrayList<ArrayList<Account>>();
oldEngines.add(listAccts);
}
public void undo() {
if (oldEngines.size() == 0) {
} else {
listAccts = oldEngines.get(oldEngines.size()-1); <--- I want this to have the same listAccts pointer.
}
All the objects in a java process share the same address space i.e. the address space of the running JVM
If I understand correctly, you want to ensure that listAccts refers to the same physical object throughout the lifetime of your code. Unless you assign listAccts to refer to a different object (in code you haven't shown us), this is a given.
After oldEngines.add(listAccts) is executed, oldEngines will contain a reference to the same object listAccts is referring to. However, listAccts is not changed in any way - it still refers to the exact same object!
So - again: unless you reassign listAccts in code you haven't shown us - the line
listAccts = oldEngines.get(oldEngines.size()-1);
looks totally unnecessary to me. In fact, it may be confusing you, if you have added other elements to oldEngines in the meantime, as then its last element won't anymore refer to the same object listAccts does.
Note also that Java doesn't have pointers, only references. All non-primitive (object) variables are actually references, not by-value copies of an object. And the JVM can actually change the physical memory location of objects under the hood, updating all references to these objects. We have no way to notice this, because there is no way to get the actual physical memory address from a reference (at least within Java - I guess you could do it using e.g. JNI). A reference is a higher level of abstraction than a pointer - it is not a memory address. This is why terms like address space are meaningless in Java.
Update
what I'm trying to do is make it so that the last oldEngine is now replacing what is the current listAccts.
If you mean to change the listAccts reference to point to the last element in oldEngine, you are already doing that. If you mean to copy the contents of the last element in oldEngine into the current listAccts object (overwriting its current contents), try
listAccts.clear();
listAccts.addAll(oldEngines.get(oldEngines.size()-1));
If you mean you want listAccts to essentially be the same object as it was before, i.e. you don't want to create a new list, then what you need to do is:
listAccts.addAll(oldEngines.get(oldEngines.size() - 1));
i.e., manipulate your existing list rather than creating a new object.
My problem was I was passing along the same old listAccts to the array list, without saying "new". Even when I did say "new" i was passing along the accounts inside of listAccts, so the arraylist would be new, but the accounts inside of the new array list would be the ones I wanted to have backups of. What I had to do was create a new object from a deep copy using this method.
http://www.javaworld.com/javaworld/javatips/jw-javatip76.html?page=2
Thanks everyone who offered help.

Learning C++ from Java , trying to make a linked list

I just started learning C++ (coming from Java) and am having some serious problems with doing anything :P Currently, I am attempting to make a linked list, but must be doing something stupid cause I keep getting "void value not ignored as it ought to be" compile errors (I have it marked where it is throwing it below). If anyone could help me with what I'm doing wrong, i would be very grateful :)
Also, I am not used to having the choice of passing by reference, address, or value, and memory management in general (currently I have all my nodes and the data declared on the heap).
If anyone has any general advice for me, I also wouldn't complain :P
Key code from LinkedListNode.cpp
LinkedListNode::LinkedListNode()
{
//set next and prev to null
pData=0; //data needs to be a pointer so we can set it to null for
//for the tail and head.
pNext=0;
pPrev=0;
}
/*
* Sets the 'next' pointer to the memory address of the inputed reference.
*/
void LinkedListNode::SetNext(LinkedListNode& _next)
{
pNext=&_next;
}
/*
* Sets the 'prev' pointer to the memory address of the inputed reference.
*/
void LinkedListNode::SetPrev(LinkedListNode& _prev)
{
pPrev=&_prev;
}
//rest of class
Key code from LinkedList.cpp
#include "LinkedList.h"
LinkedList::LinkedList()
{
// Set head and tail of linked list.
pHead = new LinkedListNode();
pTail = new LinkedListNode();
/*
* THIS IS WHERE THE ERRORS ARE.
*/
*pHead->SetNext(*pTail);
*pTail->SetPrev(*pHead);
}
//rest of class
The leading * in
*pHead->SetNext(*pTail);
*pTail->SetPrev(*pHead);
are not needed.
pHead is a pointer to a node and you call the SetNext method on it as pHead->SetNext(..) passing an object by reference.
-> has higher precedence than *
So effectively you are trying to dereference the return value of the function SetNext which does not return anything, leading to this error.
Also, I am not used to having the choice of passing by reference, address, or value, and memory management in general (currently i have all my nodes and the data declared on the heap). If anyone has any general advice for me, i also wouldn't complain :P
Ex-Java programmers always do that. And it's upside down.
You should virtually never heap-allocate data. Objects should be declared on the stack, and if they need heap-allocated memory, they should handle that internally, by allocating it in their constructors and releasing it in their destructors.
That leads to cleaner and safer code.
Class members should also be values, not pointers/references unless you specifically need the member to be shared between different objects. If the class owns its member exclusively, just make it a non-pointer value type. That way it's allocate inside the class itself, and you don't need to keep track of new/delete calls.
The simplest rule of thumb is really to not use pointers unless you have to. Do you need the object to be allocated elsewhere? Why can't it be allocated here and be accessed by value? Even if the object has to be returned from a function, or passed as parameter to another function, copying will usually take care of that. Just define appropriate copy constructors and assignment operators and copy the object when necessary.

What's your deep comprehension of pointer,reference and Handle in C,C++ and Java?

What's your deep comprehension of pointer,reference and Handle in C,C++ and Java?
We usually think about the pointer,reference and Handle on the specify language level, it's easy to make confusion by the newbie like me.
Actually all those concept in java, just a encapsulation of pointer.
All pointer just a encapsulation of main memory addresses .
So all of those ,just a encapsulation wiles.
all above, it's my personal glimpse. And what's your comprehension ?
welcome to share with me.
Each language has differences to this respect. In C there are only pointers that are variables holding a memory address. In C you can use pointer arithmetic to move through memory, if you have an array, you can get a pointer to the first element and navigate the memory by incrementing the pointer.
Java references are similar to pointers in that they refer to a location in memory, but you cannot use pointer arithmetic on them. Only assignments are allowed. Note that the reference is not the object, but a way of accessing an object. This can be seen in argument passing semantics: objects are not passed by reference, references are passed by value:
public static void swap( Object o1, Object o2 )
{
Object tmp = o1;
o1 = o2;
o2 = tmp;
}
The previous piece of code is a complex no-op. References to two objects are passed by value, they are played with inside the method and nothing happens from the caller perspective: the real objects do not suffer any change, nor do the references the caller has into those objects. That is, if the call is swap( ref1, ref2 ), the system will make copies of the references into o1 and o2, the copies are changed within the method, but the caller variables ref1 and ref2 will remain unchanged after the method call.
In C++ you have two concepts: pointers are the same as C pointers and close to Java references, while C++ references are aliases into the objects they refer. C++ references can only be initialized with one object/data element in construction and from there on, using the original object and the reference is exactly the same. Besides the fact that references don't hold the resource and thus the destructor will not be called when the reference goes out of scope, nor will the reference notice if the referred object is destroyed, for all other uses the two names are the same element.
template <typename T>
void swap( T & a, T & b )
{
T tmp( a );
a = b;
b = tmp;
}
The code above in C++ differs from the Java version in that it does change the caller objects. If a caller uses swap( var1, var2 ), then the references are bound to those variables, and it is var1 and var2 the ones that suffer the change. After the call, the value of var1 and var2 is actually swapped.
Handles are in a different level, they are not language construct but tokens provided by a library so that you can later on refer to some resource that the library manages internally. The most general case are integer handles that are ids (or offsets) into a resource table, but I have seen strings used as handles. It is the library internally who decides what is exactly a handler (a pointer, an integer, a string or a more complex data structure). Handles are meant to be opaque in that the only sensible use is to store them and later give it back to the same library as part of other function signatures.
In C++ a pointer is a variable that points to a location in memory. You can access the object or data stored there by dereferencing the pointer. A reference is simply a pointer that has two distinctions from a pointer. First, you cannot change what a reference points to once the reference is initialized. Second the dereferencing semantics are removed so you can access a reference as if it were an object allocated on the stack instead of on the heap with new.
In Java, there are no pointers, only references. Every object you use is a reference to an object allocated on the heap. The downside is you can't do pointer math tricks. That's also the upside.
EDIT:
As pointed out in the comments, a Java reference differs from a C++ reference in that it can be reassigned once initialized. They are still called 'reference types' by the language specification, but behaviorally they act like pointers in terms of being able to be reassigned and passed to functions, but the semantics of dereferencing them look like non-pointer access looks in C++.

Categories

Resources