how jvm handles creating object inside a loop - java

List list = new ArrayList();
String[] test = {"ram", "mohan", "anil", "mukesh", "mittal"};
for(int i =0; i < test.length; i++)
{
A a = new A();
a.setName(test[i]);
list.add(a);
}
How JVM handles creation of object a in each loop? How "list" differntiate between different instance? Is it good practice to create object on each iteration. If no, what is the best solution for adding object into a list.

In your example a new object is created on each iteration of the loop. The list is able to differentiate between them because it does not care that you call them all "a" in your code, it keeps track of them by the reference that gets reassigned each time you call
a = new A();
Each time that line of code is called, a new object is created on the heap and it's address in memory is assigned to the reference a. It's that reference that the list keeps a record of, not the variable name.
This is a perfectly fine and normal way to populate a list (aside from the syntax errors that others have mentioned, which I'm assuming you can fix when you try to compile your code).

List holds a reference to each instance of a that gets created. It's fine to create each object inside the loop (I'm assuming you mean as opposed to declaring the 'a' variable outside the loop and then re-assigning it each iteration).

Is it good practice to create a new object on each iteration?
One of my friends told me that it is not a good practice to creating so much instances.
If you need different individual instances, you need to create them.
Since your list needs five objects with different names each (ram, mohan, anil and so on), you need a new object for every iteration of the loop. How else are you going to store the five names?
As for declaring the variable a outside of the loop, I do not think that makes a difference performance-wise and also reduces legibility.
A a; // dont do this
for(int i =0; i < test.length; i++){
a = new A();
a.setName(test[i]);
list.add(a);
}
You might be interested in the for-each loop
for(String name: test){
A a = new A();
a.setName(name);
list.add(a);
}

If my understanding of the JVM is correct, the posted code will have no performance difference compared to
for (String name : test )
{
list.add(new A(name));
}
(assuming, of course, that the constructor A(String s) is another way to create a new instance with a specific name)

Related

Is there a way to iterate through a two dimensional ArrayList and also invoke the class methods of the objects?

So I am attempting to iterate through a two dimensional ArrayList in Java. Now I have gotten the iteration portion down, however, I can't seem to invoke methods from the object class.
I have checked my spelling to make sure that the class method was spelled correctly. It was. I have also tried iterating through the 2D ArrayList in the same fashion that one would iterate through a 2D Array (Nested For-Loops) while obviously using the ArrayList methods (.get(), .add(), etc.) to select which specific object in the 2D Arraylist that I need.
for(int i = 0; i < layers.size(); i++)
{
for(int j = 0; j < layers.get(i).size(); j++)
{
layers.get(i).get(j).calculate();
layers.get(i).get(j).activate();
input3.add(layers.get(i).get(j).getOutput());
}
}
The expected results is that the loop will have the objects preform calculations using the invoked class objects for each object in the ArrayList. However, it keeps saying that the methods I'm trying to invoke, which I know are there, cannot be found. I'm not entirely sure how to fix this issue and I can only hope that others have come across this issue and have figured out how to fix it. Thank you in advance.
Edit/Update
It should be noted that since this is coming up as an error BlueJ is not letting me compile it.
Now to understand what I mean by "2D ArrayList" here's how I coded it:
enter code here
//First lets say we have a few different ArrayLists
ArrayList<Object> list1 = new ArrayList<Object>();
ArrayList<Object> list2 = new ArrayList<Object>();
ArrayList<Object> list3 = new ArrayList<Object>();
//Now lets say you want to iterate through all of these with only a few
//lines of code... Put them into another ArrayList
ArrayList<ArrayList> bigList = new ArrayList<ArrayList>();
This is what I mean by a 2D ArrayList. A group of ArrayLists within another ArrayList.
Also the .Calculate() and .Activate() methods take in input from the instantiation of the objects not shown in the code snippet I've presented.
Is there a way to iterate through ... and also invoke the class
methods of the objects?
Yes, of course there is.
Whatever object is stored in a datastructure, you can call its methods. The problem you are facing has two aspects:
First, your list1, list2, list3,... are declared as ArrayList<Object>. This means that, whatever you put into the lists, when retrieving the compiler will only know that it's some kind of Object. Hence it only allows you to call the methods from Object on those elements. This can be worked around by explicit casts, e.g.
MyClass element = (MyClass)(layers.get(i).get(j));
element.calculate();
However, the better alternative is to use the correct generic type in the first place. Note that ArrayList<ArrayList> uses the "raw" type ArrayList as the generic type parameter, which is probably not what you want.
So, assuming the elements you store are all of the same type (MyClass for example), the clean solution would be like this:
ArrayList<MyClass> list1 = ...;
ArrayList<ArrayList<MyClass>> bigList = ...;
Now the compiler will know that inside bigList there are ArrayList<MyClass> objects, and from that, it also knows that inside the elements of bigList there are MyClass objects. Consequently, it will do the necessary casts automatically for you and you can write bigList.get(i).get(j).methodOfMyClass(...).
If the elements you store in the inner lists do not have a common (super) type, i.e. their only common super type implicitly is Object, then you will have no choice than to do the corresponding instanceof checks and casts manually.
By the way, since ArrayList (indirectly) implements the Iterable interface, you can just write
for ( ArrayList<MyClass> innerList : bigList ) {
for ( MyClass element : innerList ) {
element.methodOfMyClass(...);
}
}
to iterate over all elements of all lists contained in bigList.

How can I add an Array into a Queue?

Is it possible to add an array into specifically, a ConcurrentLinkedQueue? If so, how exactly would the .add statement look like?
THIS IS HOMEWORK RELATED, however, my entire program is meant to perform calculations on MyObjects (the default constructor of MyObjects generates random values to perform a ton of calculations on).
For example:
//Note: I couldn't use the Diamond Braces for the Queue-type when posing this question
ConcurrentLinkedQueue theLinkedQueue {MyObjects[]} =
new ConcurrentLinkedQueue{MyObjects[]}();
MyObjects[] theArray = null;
for(int i = 0; i < 100; i++){
theArray = new MyObjects[CONSTANT_SIZE];
theLinkedQueue.add(theArray(objparameter1, objparameter2));
}
The program implements multi-threading and in my thread class I've passed the Queue into the constructor, and am attempting to take off a MyObject array which a MyObject temp will point to, but so far I'm only capable of adding a single MyObject to my Queue at a time and pulling it. I want to be able to add the same amount of MyObjects as individual components rather than individually. I've attempted various lines of code only for NetBeans IDE to recommend a method to throw an UnsupportedOperation Exception. How could I add arrays into my ConcurrentLinkedQueue?
(Also apologies if my question is dense or confusing, first time posting here).
The correct syntax for the declaration of your queue is:
ConcurrentLinkedQueue<MyObjects> theLinkedQueue = new ConcurrentLinkedQueue<>();
Start with that and see how things go from there.
I figured out the solution, which was simply to add the array without 'objparameters' included.
theLinkedQueue.add(a); //where a was a 'MyObject' array.
I presumed you had to load the parameter to be passed for each array index, which seems pretty silly.

How does re instantiating work for this scenario?

I am using Java
public class MapsConfusion {
public static void main(String[] args) {
HashMap< Integer, ArrayList<String>> map = new HashMap<>();
for (int i = 0; i < 15; i++){
ArrayList<String> lst = new ArrayList<>();
lst.add("something");
lst.add("something2");
map.put(i, lst);
}
for(int j = 0; j < 11; j++){
System.out.println(map.get(j));
}
}
}
The way this works is, it creates a new arraylist each time it loops around. Here is my question,
Thinking about pointers, when you declare a new Arraylist<> each time, you are creating a new Arraylist at a new address am I correct?
Other question: Doesn't the list only exist within the scope, which is the for loop? Then how is isstill accessible when I do the other (last) for loop?
1 Question
Yes, you always create a new object and therefore a new address.
See this for further information: https://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html
2 Question
The ArrayList exists as long as at least one variable pointing at it. In this case as long as map exists and the main method runs.
Here's more about the life cycle of an object: http://www.dummies.com/programming/java/the-life-cycle-of-a-java-object/
when you declare a new Arraylist<> each time, you are creating a new
Arraylist at a new address am I correct?
Yes you are right. Each ArrayListis created at a new memory location.
Doesn't the list only exist within the scope, which is the for loop?
Then how is is still accessible when I do the other (last) for loop?
It's accessible because each newly created ArrayList gets added in to your map and that's why you do not lose it when your first for loop ends.
If you do not add each newly created ArrayList in your map, you won't be able to access any ArrayList outside the first for-loop in which it is created.
Thinking about pointers, when you declare a new Arraylist<> each time,
you are creating a new Arraylist at a new address am I correct?
Correct.
Doesn't the list only exist within the scope, which is the for loop?
Then how is is still accessible when I do the other (last) for loop?
An object is automatically deallocated by the garbage collector only when there are no references pointing to it. In your case the list is added in map, therefore it is not deallocated since there is an element of map pointing to it.
Thinking about pointers, when you declare a new Arraylist<> each time,
you are creating a new Arraylist at a new address am I correct?
Yes you are correct the pointer to the List lst only exists in the scope of the first loop.
Other question: Doesn't the list only exist within the scope, which is
the for loop? Then how is isstill accessible when I do the other
(last) for loop?
But you assigned the object the pointer lst was pointing to, into the Map map outside the looop. Therefore the object still exists because the mapentry is pointing to it.
If you move the Map also into the first loop you will get a compile error.
Since you have not removed all references to the arrayList, it will still exist and remain accessible after the first for loop. The fundamental difference is:
the arrayList won't be accessible by any variable/pointers which you have declared within the for loop, as those variables are within the scope of the first for loop only.
During the run of the first for loop, you have pointed the hashmap's value entry to each individual list and apparently the hashmap is accessible beyond the scope of the for loop.
Converging from the above two points, all arrayLists are accessible from references made in HashMap's value

How to correctly clear list in java

Lets say I have a list like this:
private LinkedList<String> messages = new LinkedList<String>();
When my method gets invoked for the first time there some strings added to this list. And I have also another method in which I need to clear this list from previously added values. To clear it I can use:
messages.clear();
This will remove all the elements from the list. Also I can create a new instance like this:
messages = new LinkedList<String>();
Which way is more proper to clear the list?
messages.clear();
Will actually clear the list, messages = new LinkedList<String>(); will just set messages as referencing a new list instance, so you could argue the first way is more "correct" to clear the list instance.
Say you have a list that is referenced by two variables, a and b. Like this (they don't have to be as close to eachother as this, they might even be in different files..):
final List<String> a = new LinkedList<String>();
final List<String> b = a;
Now, there is a big difference between
a.clear();
which will make both a and b reference the same, empty list, and
a = new LinkedList<String>();
which will make 'a' reference a new, empty list, and 'b' the old, populated list. (So they do not reference the same list).
Since you probably want them to reference the same list, a.clear() is preferred, since you won't get any surprises when your looking at the list referenced by b (which you might believe to be empty, but turns out to be populated if you use the new-approach).
I prefer the first approach i.e. messages.clear(); as it clear the elements but the List is not destroyed and recreated. All elements are removed as desired.
One side effect is there though: It iterates your list and removes one item at a time so if the list is huge then it's an unnecessary overhead.
for (Node<E> x = first; x != null; ) {
Node<E> next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
first = last = null;
size = 0;
modCount++;
Same way second approach has also one side effect: If you are using the object reference of you r list somewhere else in your program, that needs to handled properly otherwise you could get some unwanted surprises e.g. if you added your list to some other object/variable, then first approach will clear that elements from every place where it was referenced while second will not.
Summary: Both the approach outcomes are different in low level nature; though they seem to to serve your high level requirement (clearing the list). Decide carefully based on your low level requirements.
They are almost similar, but I would say messages.clear() is more flexible.
The second approach is simple and much used, but the problem where you have final modifier on your list you can not clear it that way.
messages.clear();
is more efficient. For more safety you can ask if this list is not empty befor
Personnaly I prefere to use LinkedList#clear because it is more clearly to understand during reading the code what you are doing.
But the new LinkedList<String>(); will work fine as well. So it's up to you what to use!
It clearly depends upon your need.
If you want to keep reference to your list object instance (as an example if that clear method is called inside a method in which the messages is a parameter, then the call to .clear() is the best solution.
On the other hand, if the list you want to clear is a member field (or a local variable in a method) of the object the current method is a member of, then you can call new LinkedList<String>(); without any trouble.
Notice that, to avoid the first (which I tend to disapprove), i usuall always return obejcts I modify as results from methods modifying them.
the first one is preferable. the second one makes some extra burden on the garbage collector. but the first one not.

Java clearing a list by creating a new instance

I was looking through Java code, and I came across this code:
list = new ArrayList();
uselist(list);
if (condition)
list = new ArrayList();
What's the use of this, as opposed to simply using the clear() method of ArrayLists.
is using the new command to clear a list is ok and is it faster than clearing a list ?
i am using java version 1.6
Do note that clearing and re-instantiating a list is not the same thing!
Consider this example:
a = new ArrayList();
a.add("Hello")
b = a;
a = new ArrayList(); // a is now empty while b contains hello!
Versus
a = new ArrayList();
a.add("Hello")
b = a;
a.clear(); // Both a and b are now empty.
If the side-effects (shared references) are not an issue, then it is just two ways of clearing a list. It should probably not be a performance issue unless this is called millions of times.
No, they don't do the same thing. The method clear() clears an existing list - anything which still has a reference to the list and looks at it later will see that it's empty.
The approach with the new keyword, changes the value of the list variable but does nothing to the existing ArrayList object - so if anything else has a reference to the same object, they won't see any changes.
If the list is used elsewhere calling clear() might cause side effects.
However, if that is not the case, I'd say that creating a new list instead of clearing the old one might be faster (however, probably for huge lists only, since ArrayList's clear() just iterates over the elements and set's them as null), but most likely it's just a matter of programming style.
Wether it is the same or not it depends on what uselist(...) does internally with the list.
For example, suppose you have the following code in uselist :
public void uselist(List l) {
this.mylist = l;
}
In that case, your code will create a new list and not touch this.mylist . If instead you call .clear() on it, you are clearing that same list.
The difference can be fatal and hard to see. For example hibernate will flip out of you use list = new ArrayList(); and then try to update the list in the db but it works just fine with clear() as hibernate then can see the connection.
clear() // operates on your old object
list = new ArrayList(); // list will be a new object the old will be GCed

Categories