import java.util.*;
public static void main(String[] args) {
TreeNode root = new TreeNode(8);
root.left = new TreeNode(7);
root.right = new TreeNode(6);
root.left.left = new TreeNode(5);
root.right.right = new TreeNode(4);
List<Integer> list = postorderTraversal(root);
System.out.println(list);
}
public static List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
list = helper(root, list);
return list;
}
private static List<Integer> helper(TreeNode node, List<Integer> list){
if (node != null) {
helper(node.left, list);
helper(node.right, list);
list.add(node.val);
}
return list;
}
}
In this question, I don't understand why I don't have to do list = helper(node.left, list); Why is list global here and when I'm changing my root it's local and I have to do root.left = recurse(root.left) ?
This is because of how pointers work in java.
When you pass list in as a parameter to a function, you aren't passing in the object itself, you're passing in its memory address on your computer. This memory address is called a pointer and is useful because it lets you avoid expensively duplicating objects.
You don't normally notice this because java typically hides the fact that it's using pointers at all. For instance, when you do list.add(...), it works like you're using an ordinary object and calling add() on it because java automatically substitutes the object for the pointer.
So list is kind of like a global variable, because even though the pointer is copied every time you pass it into something, it still references the same section of memory. Changing that section of memory will affect what every other pointer to that spot sees, so you get changes that other functions can see.
The statement
List<Integer> list = new ArrayList<Integer>();
Does two things. First it allocates a new ArrayList object on the heap. Then it stores a reference to that heap object in the local variable list. When you invoke helper, you are passing only the reference, which can be thought of as a memory address referring to the actual object on the heap. This reference gets passed down to the recursive invocations of helper. Each invocation gets a local copy of list, but this is only a copy of the reference, not the heap object. All those instances of list refer to the same heap object, the one you initially allocated. This is why it "feels" like it's global, but it is most definitely not.
The same concept applies to the TreeNode references, in fact to all object references in Java.
This can be highly confusing for new Java programmers. Java is "Pass-by-value", meaning that parameters are copied when invoking a method, but when the variables are objects, the "value" is a reference and not the object itself, and only the reference is copied. The only values that are copied for parameter passing are primitive values (boolean, char, int, long, float, double).
Related
I am trying to reduce the amount of memory being used in a Java project I'm working on, and one of the thing I'm looking into is using iterators of arrays, rather that copies of arrays. However, I'm not sure if this will work or not with private data inside of an object. For instance:
public class MyClass {
private ArrayList<String> data;
public ArrayList<String> getData(){ return this.data; }
public Iterator getDataIter(){ return this.data.iterator(); }
}
public static void main(String[] args) {
MyClass c = MyClass();
ArrayList<String> copyOfData = c.getData();
Iterator dataIter = c.getDataIter();
}
As you can see, in main() I couldn't just go c.data because it is private. However, c.getData() will copy the whole array. So here are my questions:
Will dataIter be able to iterate over the values in data, even though it is a private variable?
Will doing this save me any memory because I'm not passing large arrays around anymore?
c.getData() will not copy the whole array, at least, not in the code you pasted.
That makes the rest of the questions moot, but, sure, dataIter works fine here.
I suggest you review how java's memory model works. All non-primitive values (all objects) are passed around in reference form. this.data is a pointer to the array. If you return it, you return a copy of the pointer, which is a small number (64-bit usually), which refers to the array.
You can trivially test this: call .getData(), and modify something in the array. That modification will also occur in the MyClass, because there's just one array, with both the data field as well as the result of calling getData() referencing this one array.
Too many times I have to use a List of an Object instead of the object, If I use
MyObj a = null;
a.setParameter = 0;
It works.
But If I use
List<MyObj> a = null;
MyObj b = getObjectFromSomewhere();
a.add(b);
It fails with error : java.lang.NullPointerException?
And How I can see If my new List<MyObj> a is "null" or without any element inside?
A list is a container that you have to put elements into. The list has to exist prior to putting anything in it (so you can have an empty list, note).
So this:
List<MyObj> a = null;
declares a variable pointing to a null - not an actual container. Try:
List<MyObj> a = new ArrayList<>();
(note that lists come in different varieties, with different performance characteristics, and the above is just a commonly used variety chosen for illustration)
(to address your first point re a.setParameter, I guess that is a static method - defined for the class, not the instance of a class - and confusingly Java will let you reference that via an instance)
Eclipse allows you to initiate it to a null because Eclipse thinks that you will be pointing an object to this reference somewhere later in your code.
so its your responsibility to have it refer to an object before using any of the List methods.
doing this List<MyObj> a = null makes no initialization in memory so a point to nothing
what you should do is
List<MyObj> a = new ArrayList<>();
a.add(getObjectFromSomewhere());
How I can see If my new List a is "null" or without any element
inside?
if(a == null){...} // to check if array not initialized
if(a.size() == 0){...} // to check if array have no element
keep in mind calling a.size() when a is null will throw NullPointerException
while studying a linked list implementation i need a clarify how the reference and object store in stack and heap for this kind of scenario where object it self has references,
public class MyLinkedList {
private Node head;
private int listCount;
public MyLinkedList() {
head = new Node("0");
listCount = 0;
}
public void add(Object data) {
Node nodeTemp = new Node(data);
Node nodeCurr = head;
while (nodeCurr.getNext() != null) {
nodeCurr = nodeCurr.getNext();
}
nodeCurr.setNext(nodeTemp);
listCount++;
}
}
public class LinkedListMain {
public static void main(String[] args) {
MyLinkedList ls = new MyLinkedList();
ls.add("1");
}
Now MyLinkedList object is refer by "ls" reference which is in stack and the MyLinkedList it self is in heap. That i understood.
But then from the MyLinkedList constructor when we create new Node which refer by "head" reference where does that "head" reference store? My doubt is since "Node head" is inside (belong to) MyLinkedList object, does "head" store in stack with "ls" or is it kind of inside MyLinkedList object?
Two important things about Java you need to understand:
All Java objects are allocated in the Java heap. All of them.
In Java, variables are never objects. Never. But a variable can be a reference to an object. (Or a variable can be a primitive like int, but those are also not objects.)
What this means is that your main method allocates a MyLinkedList object, on the Java heap, and stores a reference to that object in a variable named ls. That MyLinkedList object (which itself doesn't have a name) can store a reference to a Node object (which will also be stored on the Java heap) in a local field called head.
No other object is ever stored "inside" any object. Only references to other objects are stored inside.
Caveat: While this answer is correct I'm regard to how the Java language works, the runtime is allowed to make various optimizations as long as you can't tell the difference. For example, "the Java heap" is not a heap in the algorithmic sense, and often not even in the same sense as "the C++ heap". The Java JIT is allowed to allocate Java objects from a stack-like structure (the younggen) or even from the current stack (due to escape analysis). That said, those implementation details are not relevant when you're just learning the language.
The "MyLinkedList" object allocated in main() is reference by "ls".
"ls" is on the stack - a local variable of main.
The members of this instance of "MyListedList" are on the heap.
In add(), nodeTemp and nodeCurr are stack variables which are references to nodes. The nodes themselves are on the heap.
"head" is a class member variable, and is on the heap, along with listcount.
In Java, (non-static) class members must always be on the heap.
All the instance variables & objects are stored on the heap. Whereas local variables are on the stack. headwill be on the heap & ls will be on stack.
public class MyLinkedList {
private Node head;
private int listCount;
head & listCount both will be on heap.
I'm working on an assignment that deals with array manipulations for Java. Right now I have to delete elements inside the middle of an array. Now I know that arrays, once they're created cannot be changed in length. So I decided to make a new object, and have the former reference point to my new array.
public class A{
public static void main(String[] args){
B test = new B(val);
test.cut(2,4);
test.display();
}
class B{
private Obj[] array;
B(Obj val){
construct something
}
public void cut(int i, int j){
B newObject = new B(val);
...
newObject.array = this.array;
newObject = this;
}
}
The issue is that when I display the test object, it will only show me the original test object contents rather than newObject contents. Since this is a void method, I can't return an object. How do I reference the new object then? The last two lines for my cut method seem to have no effect at all. I know that ArrayList would be preferable for things like this, but this being a homework assignment we are forced to use arrays.
Now I know that arrays, once they're created cannot be changed in length.
This is true.
But the reference pointing to an array inside the B object instance can be changed (as you didn't declare it final):
public void cut(int i, int j){
Object[] newArray = new Object[len];
//... copying array content ...
this.array = newArray;
}
Beware of the thread safety issues such mutability causes. Mutable objects are usually frowned upon...
If the rules of assignment allow the use of class Arrays, this is what you can use instead of your own cut method:
newArray = Arrays.copyOfRange(oldArray, from, to);
In the method cut you create a new object of B then assign the the this reference to it. This has not effect as you have found because the this reference (the actual object) is not changed at all, The newObject is visible only inside this method, once it is terminated, the object is gone.
While you are in the same class B you dont have to create a new Object of it just for the purpose of altering the data it holds. You could just create a new array and copy the original content to it.
For copying the content you could use the method System#arraycopy. If you are not permited to use any jdk helping functionalities, then you could just loop over the original array and copy elements into the new one as you want.
Is there a way to move the entire contents of an ArrayList to another instance of ArrayList in O(1)?
I.e.: only the reference to the backing array is passed from one instance to the other (elements are not copied one by one).
For example:
ArrayList<String> a = new ArrayList<>(Arrays.asList("A", "B", "C"));
ArrayList<String> b = new ArrayList<>();
a.moveContentsTo(b);
// 'a' is now empty, while 'b' contains everything that 'a' did before and 'a != b'
// It is desired that the 'moveContentsTo' method is O(1)
Even better, is there an ArrayList#swapContents(ArrayList) method?
Further explanation and use-case:
Further explanation 1: the references of 'a' and 'b' must not be exchanged. I am not looking for tmp = a; a = b; b = tmp; type of solutions.
Further explanation 2: The operation must be ~O(1) in time.
The use-case: This is useful when an object wants to encapsulate a list constructed outside:
public class A {
private ArrayList<String> items = new ArrayList<>();
/**
* This method takes the sole ownership of the contents. Whoever
* passed the list from the outside will not be able to modify
* contents of 'this.items' from outside the class.
*/
public AnImmutableObject(ArrayList<String> items) {
if (items != null) {
items.moveContentsTo(this.items);
}
}
/**
* Other collections that do not provide the 'move' functionality
* must be copied. If we just stored the reference to 'items' we
* would break encapsulation as whoever called the constructor
* still have write capabilities to the collection.
*/
public A(Collection<String> items) {
if (items != null) {
this.items.addAll(items);
}
}
public List<String> getItems() {
return Collections.unmodifiableList(items);
}
}
Notice that we want to avoid making a copy (to increase speed and decrease memory usage). The crucial bit is that the callee must lose the ability to modify the (now encapsulated) ArrayList.
#Lirik answer is greate +1. However, if you are looking for a real ArrayList#swapContents(ArrayList), here is how you can do it:
public static void swapContents(ArrayList<String> listA, ArrayList<String> listB)
{
List<String> temp = new ArrayList<String>(listA);
listA.clear();
listA.addAll(listB);
listB.clear();
listB.addAll(temp);
}
AFAIK, it's very not Java-like to keep track of "ownership" of references (at least on the programmer's side) which is why I doubt that you'll find the std::move()-like functionality that you want. It just isn't very commonly needed in Java.
I guess C++ needs to keep track of object ownership explicitly because there is no garbage collection.
I think that your best bet is to create a defensive copy in your constructor and save space by relying on copy constructors of immutable objects:
public class AnImmutableObject {
private final List<String> items;
/**
* Creates a new immutable object with the given list of items.
* Always deep copy from an outside source, because we can't know if the
* calling code will modify that collection later.
*/
public AnImmutableObject(Collection<String> items) {
// It's a constructor. We know items needs to be set.
// We are creating a new array list, using its constructor which deep
// copies the collection, and immediately wrapping it to make it truly
// immutable. We are guaranteed that no one will hold a reference to the
// mutable view of the new ArrayList.
this.items = Collections.unmodifiableList(new ArrayList<String>(items));
}
/**
* Creates a new immutable object with the same items as another.
* Copying the reference here is completely safe because we
* enforce the immutability of the items array.
*/
public AnImmutableObject(AnImmutableObject source) {
items = source.items;
}
public List<String> getItems() {
return items;
}
}
At this point, you can "pass the arrays around" (really share them) in O(1) between your own immutable objects:
ImmutableObject a = new ImmutableObject(Arrays.asList("A", "B", "C")); // O(n)
ImmutableObject b = new ImmutableObject(a); // O(1)
Hopefully, something like this can suit your purposes.
Another route you could go is use Guava's ImmutableList. Since these are immutable, you can safely copy the reference to the ImmutableList in a constructor.
The main approach is about making it safe for you to copy references to the lists rather than taking ownership over them.
This should do it:
ArrayList<String> a = new ArrayList<>(Arrays.asList("A", "B", "C"));
ArrayList<String> b = a;
a = new ArrayList<>();
Conceptually speaking, a is now empty and b contains what a contained before. There was a single assignment and no copying of data, which is about the fastest you can do it. Does that satisfy your requirement, or do you actually want a to still reference the same array except that the given array should now be empty?
Update
I don't believe that in C++ the time complexity for the move operation is O(1) either. It's also prudent to point out that "because classes in Java use reference semantics, there are never any implicit copies of objects in those languages. The problem move semantics solve does not and has never existed in Java." (see the answer by FredOverflow: C++ Rvalue references and move semantics)
Is there a way to move the entire contents of an ArrayList to another ArrayList so that only the reference to the backing array is passed from one to the other (i.e., so that elements are not copied one by one).
Given the above statement, then if you copy something from array a to array b in Java, both arrays will reference the same data. All that you do with move semantics in C++ is that you save the temporary object which needs to be created in order to make such a copy:
X foo();
X x;
// perhaps use x in various ways
x = foo();
The last one does:
destructs the resource held by x,
clones the resource from the temporary returned by foo,
destructs the temporary and thereby releases its resource.
Move semantics does:
swap resource pointers (handles) between x and the temporary,
temporary's destructor destruct x's original resource.
You save one destruct, but only in C++... the above problem does not exist in Java! See this article for more details on move semantics: http://thbecker.net/articles/rvalue_references/section_02.html