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
Related
So, sort of in continuation of this post: What is the difference between ArrayList.clear() and ArrayList.removeAll()?... Are there certain situations where it is actually better to use removeAll() instead of clear()?
Also, to add onto this question, if I know I'm clearing all the contents of an ArrayList, would it be ok to set it to a new ArrayList?
ArrayList myList = new ArrayList<String>();
myList.add("a");
myList.add("b");
// instead of using: myList.clear();
myList = new ArrayList<String>()
If the above is ok to do, again, why use clear() vs setting to a new ArrayList? Creating a new, empty ArrayList is faster than O(n).
Why use clear() instead of creating a new ArrayList? Several reasons:
You might not be allowed to reassign a reference field that points to an ArrayList, so you can clear an existing list but not put a new one in its place. For example:
class MyData {
// Can clear() but not reassign
final List<Object> list = new ArrayList<>();
}
The variable might be declared as List. The actual type could be LinkedList and you want to preserve it instead of replacing the implementation with an ArrayList.
It's not necessarily true that clear() is O(n) time. One implementation strategy is to nullify all the existing elements in the backing array in O(n) time. But another equally valid implementation is to throw away that internal array and replace it with a new one, preferably a short array for O(1) time.
There is no ArrayList.removeAll().
But there is an ArrayList.removeAll(Collection).
The method clear() should be faster than removeAll(Collection) because removeAll(Collection) does some comparisions to decide if an object should be removed from the list. The clear() method simply removes everything without thinking.
if you want to remove a specific collection from your list but you don't want to remove everything, you will use remove all with the collection that you want to remove.
I am iterating over a List of Lists. In my code listofuserdetailsperAccount is List<List>. I am considering the two methods below, please let me know which way is correct, more efficient and should be followed in java coding.
Way 1-----
for(int i=0;i<=listofuserdetailsperAccount.size();i++){
List list=(List) listofuserdetailsperAccount.get(0);
}
Way 2---
for(int i=0;i<=listofuserdetailsperAccount.size();i++){
List list= new ArrayList();
list=(List) listofuserdetailsperAccount.get(0);
}
I'll go with for each loop
for( List userDetailsPerAccount : listOfUserDetailsPerAccount ) {
//anything you want to do with userDetailsPerAccount
}
Way 1 is better approach than Way 2. In Way 2 List list= new ArrayList(); it will create a extra ArrayList object which does not have any use, which will cause memory consumption for sometime.
And it is also recommended use type specific List<E> so that you dont cast at runtime it will be typesafe.
for(List<E> list : listOfUserDetailsPerAccount){
...
}
In Java 5 and above use for-each.
You have a couple of problems here, with both proposed solutions.
Your List<List> listofuserdetailsperAccount object is not properly typed, as the inner List is a raw type, something to be avoided. Assuming your inner list holds UserDetail objects, your list of lists should be of type List<List<UserDetail>>.
You don't use the for-each loop syntax to iterate over a List, which is Iterable.
for(List<UserDetail> innerList : listofuserdetailsperAccount)
In Way 2 you initialize List to a new ArrayList (which is a raw type, it should be new ArrayList<>() if you needed this) and then promptly overwrite this value with the contents of your outer list. This means you ask Java to construct a new object that is then immediately cleaned up by the garbage collector, unused. This is wasteful and unnecessary.
In summary, you likely want to do:
List<List<UserDetail>> listofuserdetailsperAccount = // initialize your list
for(List<userDetail> innerList : listofuserdetailsperAccount) {
// do work with your innerList now
}
You commented (tidied up):
So while initializing I am doing something like this now, can you please let me know if this is correct:
List<List<String>> listofAccountdetailsLoggedinUser = null;
listofAccountdetailsLoggedinUser = new ArrayList<List<String>>();
OR I should not put it as null and directly create an object like this:
List<List<String>> listofAccountdetailsLoggedinUser =
new ArrayList<List<String>>();
That is the right track, but you do not need to initialize the variable to null. It doesn't hurt anything, since it doesn't construct an unnecessary object, but there's no reason to - you can declare and initialize the variable in one line, like you do in your second example.
Additionally, you don't need to specify the type of the ArrayList on the right hand side, simply use the diamond operator <>, like so:
List<List<String>> listofAccountdetailsLoggedinUser = new ArrayList<>();
Also, consider a shorter variable name, there's no need to use such a long one, and it's no fun to type :)
I have an object stored in a global variable let's say:
static ArrayList<Object> list = new ArrayList<Object>();
I want to store it later to look into it without actually changing the values in the structure itself. So I am doing something similar to this:
public void someMethod()
{
ArrayList<Object> tempList = new ArrayList<Object>();
tempList = list;
list.remove(0);
}
I'm thinking this may have something to do with me initializing the variable as "static". I don't usually do that but Eclipse told me I had to so I just let the change happen.
My understanding would be that I am storing the original list into a temporary list and anything I do to the temporary list would be independent of the original list. But it appears that if I were to remove something from this above list, that the original list is removing it as well.
I remember learning that this could happen sometimes but I think I've done this before without having that issue.
I apologize if this is a repeated question but the way I worded it didn't show me an question that was similar.
Thanks!
My understanding would be that I am storing the original list into a temporary list and anything I do to the temporary list would be independent of the original list.
This is not the case. When you do something like
a = b;
then both a and b refer to the same object. Mutations in a show up in b and vice verse (since there is only a single object in question). In this case you probably want to use the copy constructor of ArrayList:
ArrayList<Object> tempList = new ArrayList<Object>(list);
Notice that here we are explicitly creating a new, independent object and assigning that to tempList.
Note that this creates what's called a shallow copy: the objects referenced by the list themselves are not copied, but instead a new list is created that contains the references to the same objects as the original list.
At the end of your someMethod, your tempList disappears into the dark void of the GC. If you want to keep it, you need to turn it into a similar field as list is.
Also, assigning list to tempList makes you have two references to the same object.
I have the following code in ThisClass:
static ArrayList<MyClass> classlist;
If I call:
ThisClass.classlist = new ArrayList<MyClass>();
ThisClass.classlist.add(object);
And then call this line again:
ThisClass.classlist = new ArrayList<MyClass>();
Will it reset the ThisClass.classlist list, i.e. the classlist list will no longer contain object?
Here's an illustration:
Code 1: Creating the ArrayList and Adding an Object
ThisClass.classlist = new ArrayList<MyClass>();
ThisClass.classlist.add(object);
Results into this:
Code 2: Resetting through Re-initialization
ThisClass.classlist = new ArrayList<MyClass>();
Results into this - you're resetting it by making it point to a fresh object:
Code 3: Resetting by clearing the objects
What you should do to make it "no longer contain an object" is:
ThisClass.classlist.clear();
Clear loops through all elements and makes them null. Well internally the ArrayList also points to the memory address of its objects, but for simplicity, just think that they're being "deleted" when you call this method.
Code 4: Resetting the entire classlist
If you want to make it "no longer contain an ArrayList" you do:
ThisClass.classlist = null;
Which means this:
Also, take note that your question's title mentions "static ArrayList". static doesn't matter in this context. The result of your problem will be the same whether the object is static or not.
Calling
ThisClass.classlist = new ArrayList<MyClass>();
does will clear the ThisClass.classlist array (actually, will create a new ArrayList and place it where the old one was).
That being said, it is much better to use:
ThisClass.classlist.clear();
It is a way clearer approach: shows your true intention in the code, indicating what you are really trying to accomplish, thus making you code more readable/maintainable.
Correct.
Technically, you do not clear the ArrayList doing so, you actually instantiate a new empty ArrayList.
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.