I have an one scenario in my application,
I have to add 20 POJO objects into ArrayList. In that case I have a method like below.
public void methodname() {
ArrayList arr = new ArrayList();
for(int i=0;i<20;i++) {
User userobj = new User();
userobj.setName("xxx");
userobj.setFirstName("xxx");
userobj.setLastName("yyy");
arr.add(userobj);
} // end of for loop
}
one of friends suggest to change the UserObj declaration outside for loop.
public void methodname() {
User userobj = new User();
ArrayList arr = new ArrayList();
for(int i=0;i<20;i++) {
userobj.setName("xxx");
userobj.setFirstName("xxx");
userobj.setLastName("yyy");
arr.add(userobj);
} // end of for loop
}
in the first approach, I created the userobj inside the for loop, so when next iteration comes previous userobj will be eligible for garbage collector..
I would like to know is there any significant performance will improve on the second approach?
I would like to know is there any significant performance will improve on the second approach?
Did you experience a difference?
When programming you should focus on correctness and readability of your code.
Do not even Think about performance unless you have an actual performance problem and you have proven by profiling that a certain construct is the cause.
The ultimate universal performance tip is:
The fastest way to do something is not doing it.
So focus on good algorithms that avoid unneeded/hidden loops rather than on syntax variants that may improve performance.
The main difference between the first and the second approach is that in the first case you create 20 different User in memory which are assigned to the array.
In the second case you create only one User in memory but change its properties 20 times and assign the same User to all 20 positions of the array.
Regardless of the first scenario or the second, your User instances created are eligible for garbage collection only when the array itself is eligible for garbage collection, expect you remove the association with the array.
Garbage collection takes place only for an instance if there is no other instance referencing it.
Both the ways, will produce different results.
In the First one, you create 20 separate Objects, and add them to the List. Thus, changes on one of them, won't affect the others.
The Second, however, has the same object. Thus, changes on one will reflect the others. Actually, at the end, the attributes of the all the Objects would be the same, i.e, equal to the last added Object
Performance-wise, you can't say. The Objects would only be eligible for garbage collection, when there are no references pointing to them. However, as both the ways perform separate functions, you can't compare them.
Alas, your Friend is wrong. The First way is what you're looking for.
It needs to be inside the loop, otherwise you are only adding the SAME user 20 times !
On the second approach you will have only one last object in the list
I think that the right way is:
- declaration outside
- instantiation inside
public void methodname() {
ArrayList arr = new ArrayList();
User userobj;
for(int i=0;i<20;i++) {
userobj = new User();
userobj.setName("xxx");
userobj.setFirstName("xxx");
userobj.setLastName("yyy");
arr.add(userobj);
} // end of for loop
}
Related
Does Java replace an object if it was the same name? This question comes to my mind daily.
Example 1: If I create an object 500 million times with the same object name, does Java create 500 million objects, or will it replace it and stay there in one object?
for (int x = 0; x < 500000000; x++) {
TestObject testObject = new TestObject();
}
Example 2: Which way is better to avoid creating a new object every click?
//Using this way?
List < ActivityManager.RunningServiceInfo > runningServiceInfoList = getRunningService();
activityMainBinding.activityMainConstraintLayout19.setOnClickListener(v - > {
runningServiceInfoList.clear();
runningServiceInfoList = getRunningService();
if (...)
});
//Or this way?
activityMainBinding.activityMainConstraintLayout19.setOnClickListener(v - > {
List < ActivityManager.RunningServiceInfo > runningServiceInfoList = getRunningService();
if (...)
});
Does Java will create 500 million objects
It might create no objects at all, if escape analysis determines that it doesn't need to, since it can just work with the field values on the heap instead.
Worrying about the number of objects created is worrying about things at the wrong level. Think about correctness first, speed later:
If TestObject is immutable, there is no reason to create it in the loop: you can create it inside the loop if you want, or move it outside and reuse the instance.
If TestObject is mutable, is there a risk that you will unintentionally leave state from previous iterations, which will corrupt the calculation in the current iteration? If so, unless creating a new TestObject is really expensive, just create new instances in the loop, because it's then more obviously correct. The JVM is really good at optimizing the life cycle of short-lived objects.
The fact that you're using the same name (in example 1), or even re-assigning to the same variable (in the first snippet of example 2) is inconsequential. A new object will be created, and the old object will be eligible for garbage collection.
I want to delete remove the reference to a large array by nulling the reference after I used it. This gives me a compiler error however, since the parallel assignment to the array requires the array to be (effectivly) final (at least that is what I think the problem is...). How can I allow the garbage collection to remove the array?
double[][] arr = new double[n][n];
IntStream.range(0, n).parallel().forEach(i -> {
for(int j=0;j<i;j++) {
directDistances[i][j] = directDistances[j][i] = ...;
}
});
//Use arr here...
arr = null; //arr no longer needed.
//This gives the error "Local variable defined in an enclosing scope must be final or effectively final."
I want to delete remove the reference to a large array by nulling the reference after I used it
Don't.
All implementations that I am aware of in the JVM world, will scan thread stacks to find out reachable objects. This means that scope of the method has nothing to do with how long an Object is kept alive. In simpler words:
void yourMethod(){
byte [] bytes = ....
// use bytes array somehow
// stop using the byte array
// .... 10_000 lines of code
// done
}
immediately after the line // stop using the byte array, bytes IS eligible for garbage collection. It is not going to be eligible after the method ends. scope of the method (everything between { and }) does not influence how much bytes is going to stay alive. here is an example that proves this.
The array becomes eligible for garbage collection at the latest when the method returns - you don't need to set it to null.
If you have a long method and are concerned that the array is kept around for the rest of it, the solution is to write smaller methods. Dividing the functionality among smaller methods may also improve readability and reusability.
If you can't or don't want to write smaller methods, introducing separate blocks in the method may help. Local variable declarations are local to the block, so this "trick" also lets you re-use a variable name in different blocks in the method.
void largeMethod() {
first: {
final int number = 1;
}
second: {
final int number = 2;
}
}
Technically, the array becomes eligible for garbage collection after its last use, which can be in the middle of the method - before the variable goes out of scope. This is explicitly allowed by section 12.6.1 in the language specification:
Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.
While the specification allows this optimization, it does not require it. If you find that the optimization is not being made in a particular situation and you need a better guarantee, splitting the big method into smaller methods will help.
Use AtomicReference ar = new AtomicReference () ; ar. set(arr) ;
This will provide you with an effectively final array
Then use ar.set() and ar.get() methods to modify the array
I'm new to java. I came through the following code while reading an introductory book on Java while reading about the finalize method.
class FDemo{ int x;
FDemo(int i){
x=i;
}
protected void finalize(){
System.out.println("Finalizing " +x)
}
void generator(int i) {
FDemo o= new FDemo(i);
}
}
Now while creating objects I encountered the following in the new class
int count;
FDemo ob= new FDemo(0);
for (count=1;count<10000000;count++)
ob.generator(count);
I'm having trouble understanding how are we creating new objects using the same name 'o' in the for loop? Would we have to create a new object and then on the next iteration discard the existing object 'o' throughout the loop?
Also, why does finalize execute for 10 million but not for 1000 if we are constantly creating and discarding the same object? Like I said, I'm a beginner and this question might sound very basic or even silly for most of the people here but I would appreciate it very much if you could take out a few minutes to answer.
Thank you
Also, why does finalize execute for 10 million but not for 1000 if we
are constantly creating and discarding the same object
You really create 10 million distinct objects in this applications's lifetime, each of which gets referenced by o , one after the other.
Each time, the de-referenced one becomes eligible for garbage collection, because it has become unreachable from the application, and the garbage collector then calls it's finalize method.
How are we creating new objects using the same name 'o' in the for loop?
You should learn some C and how pointers works, Java hide this, so it can be weird some time.
In Java, there is 2 type of data : objects (like String or your FDemo) and primitives (like int, char...).
Variables that references a primitive works like you intended to, each time you give it a new value, it erase the previous one.
Variables that references objects don't work that way, they are pointers. A pointer can be seen as an address. It's clearer in C (and C++), where they are in fact primitives and can be print as well.
Next come the life time of your variables. When you quit the section where you variable is declared, it's cease to exist (but objects are not automatically destroyed and I think it's the purpose of your exercise).
As example :
public void someMethod() {
int a = 1;
// I have access to a
{ // I create a new section, generally, it's use by condition, loop...
int b = 2;
// Here I have access to a and b
} // End of my section
// b is destroyed, I still have access to a
}
// I'm outside my method, a is destroyed
Why does finalize execute for 10 million but not for 1000 if we are constantly creating and discarding the same object?
That's the purpose of the Java's Garbage Collector. It's a big system used to clean memory. It destroys (call the finalize() method) all object that don't have pointers that references them. It's only called when you really need it, because it can use a lot of processing power (in old machine, applications could freeze when the garbage collector starts).
Your object is very simple (only 1 primitive), so it doesn't use a lot of memory. That's why the garbage collector is called only when you create 10 millions objects.
Ok I'm going to break this up into parts.
How are we creating new objects using the same name 'o' in the for
loop?
So, what you are doing here is actually just overriding/re-assiging the reference variable of o to a differnt FDemo. That leaves the old one empty and eventually gets destroyed by garbage collector. (Which is what invokes the finalize() method)
Would we have to create a new object and then on the next iteration
discard the existing object 'o' throughout the loop?
Well that is exactly what you are doing, when you re assign o you are overwriting the old one.
Also, why does finalize execute for 10 million but not for 1000 if we
are constantly creating and discarding the same object?
Well, this is because java's trash collector is only triggered when a massive amount of objects are made. However, I am surprised that 100000 didn't do it.
The thing you have to remember about finalize(), its only called on the trash collection of the object. Now, thats a very unreliable process and isn't really within your control. Like #TT. said in the comments, dont rely on this. The program that you have written simpliy forces the finalize() method to eventually be invoked due to generating a massive amount of objects intentionally. It's a good way to learn about finalize and how it works, but in practice this may not be a great solution.
I often come across cases where I want to use an enchanced for-loop for some Collection or array that I get from some object.
e.g.
items = basket.getItems();
for (int item : items) {
// Do something
}
Another way to do that is:
for (int item : basket.getItems()) {
// Do something
}
The second one is more compact and improves readability in my opinion, especially when the item variable won't be used anywhere else.
I would like to know whether the getter in the for statement has any impact in performance. Will it be optimized to something similar to the 1st one? Or will it access the getter every time? Of course the getItems() might do something quite slow (e.g. network access, etc)
Question is similar to some others, but is referring to the getter of the collection/array itself and not the size of it. However, it may be the same case in the end.
The getItems() method will be called only once in both cases. There is no difference between the two, apart from one using an extra local variable which you could use somewhere else.
As you can read in JLS 14.14.2, the enhanced for loop is translated roughly to this traditional for loop:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
TargetType Identifier = (TargetType) #i.next();
Statement
}
#i is an automatically generated identifier that is distinct from any other identifiers (automatically generated or otherwise) that are in scope (ยง6.3) at the point where the enhanced for statement occurs.
From here it's clear that Expression is evaluted only once.
As you can see on the following code sample, on the enhanced for, the initialization of the collection on which to iterate is done only once. So, the second choice is more compact, and does not impact performance.
package test;
public class Main {
static class Basket {
int[] items = { 1, 2, 3 };
public int[] getItems() {
System.out.println("in getItems()");
return items;
}
}
public static void main(String[] args) {
Basket basket = new Basket();
for (int item : basket.getItems()) {
System.out.println(item);
}
}
}
Yes second one improves readability of code.
if you are getting the objects from network and then iterating over it in a for loop then I think yes it has performance impact because you are making network access every time and that is inefficient also as for a small/single object doing network access is not recommended. instead of that get it once from network access store it locally and iterate over it
thus 1st option is performance optimized in network access case
if your object is local then any method will do. there wont be much performance difference.
I don't think it will call getter every time. If it does it will get new list every time and Loop wont break. You can test this by putting simple Sysout inside getter method. Performance will be same in these two cases.
I have a class as following which is used to retrieve all users and all online users from database, after retrieval they put the results in "users" variable to be used by jsp.
I am wondering on which line should I have List users = new ArrayList ? to consume less memory and to be efficient? Please note just two of methods use it.
*I know if I do not create it in constructor I would need to create it in all methods that going to use it, but as just two methods are using it does it make sense to create it in constructor? Please give me your reasoning, I want to learn.
public class Groups {
private List<User> users;
public Groups(){
//Line 1 users = new ArrayList<User>;
//Line 2 if (users == null) {
// users = new ArrayList<User>();
// }
}
public retrieveAllGrades(){
...
}
public retrieveAllUsers(){
//Line 3 users = new ArrayList<User>;
this method uses it to keep the results of all users retrieved from database
}
public retrieveOnlineUsers(){
//Line 4 users = new ArrayList<User>;
this method uses it to keep the results of all online users retrieved from database
}
all getters and setters
}
In general you want to allocate memory in the constructor so that it can be shared by methods, even if it is just two of them
If you are concened about memory, you can use lazy allocation and only allocate it if needed. So you can start with users as null, but declare it as null in the constructor
Then if either method is called, you can check if it is null then you allocate (call to new). Keep in mind this can cause more complications in multithreaded code and will cost you a bit of cpu everytime either method is called because you have to check for null
Example of lazy allocation:
public Groups(){
users = null;
}
public retrieveAllUsers(){
if (users == null) users = new ArrayList<User>;
// this method uses it to keep the results of all users retrieved from database
}
public retrieveOnlineUsers(){
if (users == null) users = new ArrayList<User>;
// this method uses it to keep the results of all online users retrieved from database
}
Constructor is the place where you should be doing this.
Putting it anywhere else might look little memory efficient to you for sometime but it'll have a big tradeoff over design. Suppose you allocate memory in retrieveOnlineUsers() but the how do you guarantee the order of operation on "users". If retrieveAllUsers() is called first without allocating memory and performing some tasks, you'll fall into NPE. At the time of writing you might guarantee that retrieveOnlineUsers() is always called first but in future somebody else looking at your code will never know that retrieveAllUsers() shouldn't be called first.
Constructor guarantees that no other method would be called before it and hence every function will have concrete definition of "users".
However, if you have decided NOT to initialize it in constructor, then keep a null check in methods which are going to access "users" and define it if it is NULL. Although, this is not the case here but mentioning it for future- In these situations of lazy initialization, you need to be extra careful if you are running in multi-threaded environment and your methods are static. It might create a race condition. There is a lot to it but not discussion as it'll go well beyond the complexity of the question asked.