list.clear() vs list = new ArrayListInteger();
It's hard to know without a benchmark, but if you have lots of items in your ArrayList and the average size is lower, it might be faster to make a new ArrayList.
http://www.docjar.com/html/api/java/util/ArrayList.java.html
public void clear() {
modCount++;
// Let gc do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
Polymorphism: Why use List list = new ArrayList instead of ArrayList list = new ArrayList?
The main reason you'd do this is to decouple your code from a specific implementation of the interface. When you write your code like this:
List list = new ArrayList();
the rest of your code only knows that data is of type List
, which is preferable because it allows you to switch between different implementations of the List
interface with ease.
For instance, say you were writing a fairly large 3rd party library, and say that you decided to implement the core of your library with a LinkedList
. If your library relies heavily on accessing elements in these lists, then eventually you'll find that you've made a poor design decision; you'll realize that you should have used an ArrayList
(which gives O(1) access time) instead of a LinkedList
(which gives O(n) access time). Assuming you have been programming to an interface, making such a change is easy. You would simply change the instance of List
from,
List list = new LinkedList();
to
List list = new ArrayList();
and you know that this will work because you have written your code to follow the contract provided by the List
interface.
On the other hand, if you had implemented the core of your library using LinkedList list = new LinkedList()
, making such a change wouldn't be as easy, as there is no guarantee that the rest of your code doesn't make use of methods specific to the LinkedList
class.
All in all, the choice is simply a matter of design... but this kind of design is very important (especially when working on large projects), as it will allow you to make implementation-specific changes later without breaking existing code.
Why clear() on one ArrayList is clearing elements in another ArrayList?
tl;dr
You said:
Are result and list ArrayList pointing to the same reference
Yes.
To add a copy, change this:
result.add( list );
… to this:
result.add( new ArrayList<>( list ) );
Details
You might be thinking that result.add(list);
is adding the contents of list
. But no, that call passes the reference (pointer, memory address) of the ArrayList
object you named list
. The contents of list
are irrelevant to that call. Whether empty or full, the list itself, the container, is what you are passing to add
.
So you are adding the very same list five times. All the elements of result
point to the very same single list. If you add to the contained list, all five elements of result
see that change. If you clear that added list
, all five elements of result
see that change, all five elements of result
point to the same single now-empty list.
To add different unmodifiable lists, call List.copyOf
.
result.add( List.copyOf( list ) );
To add different modifiable lists, construct new ArrayList
objects. Pass an existing list to the constructor of a new list.
result.add( new ArrayList<>( list ) );
What does ListInteger list = new ArrayListInteger(); actually mean?
In both your examples, only the expression new
creates instances of objects (the right hand side of the =
), the left hand side only defines a variable that points to the object that you created.
In both cases, the object that you create is of type ArrayList
.
List
is an interface, not a class, and interfaces themselves cannot be instantiated. But ArrayList
implements the interface List
, so you can assign an instance of ArrayList
to a variable of type List
.
The advantage of Example 1 is that you can later decide to create another implementation of List
(like LinkedList
) and all your code that was using the List
type for variables will still work without any change. While in Example 2, if you later decide that you need a different type of List
, you need to change the type of all your variables that point to the actual object.
Your questions:
But what I want to know what Example 1 actually means. Does it create
a new List? Or does it create a new ArrayList?
It creates a new ArrayList
.
Does the resulting object have the properties of a List? Or does the
resulting object have the properties of an ArrayList?
The resulting object has all the properties of an ArrayList
.
However, through the variable list
which as type List
, you can only access the methods defined in the interfaces List
.
But you can use type-casting to access the methods in ArrayList
like this, if you later need to (but there is little reason as ArrayList doesn't have much beyond what's in List)
List<Integer> list = new ArrayList<Integer>(); //Example 1
ArrayList<Integer> arrayList = (ArrayList<Integer>) list; // type-cast
what is the sense of final ArrayList?
But what is effect making it's final?
This means that you cannot rebind the variable to point to a different collection instance:
final List<Integer> list = new ArrayList<Integer>();
list = new ArrayList<Integer>(); // Since `list' is final, this won't compile
As a matter of style, I declare most references that I don't intend to change as final
.
I still can add to ArrayList new elements, remove elements and update it.
If you wish, you can prevent insertion, removal etc by using Collections.unmodifiableList()
:
final List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>(...));
What is the difference between ArrayList.clear() and ArrayList.removeAll()?
The source code for clear()
:
public void clear() {
modCount++;
// Let gc do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
The source code for removeAll()
(As defined in AbstractCollection
):
public boolean removeAll(Collection<?> c) {
boolean modified = false;
Iterator<?> e = iterator();
while (e.hasNext()) {
if (c.contains(e.next())) {
e.remove();
modified = true;
}
}
return modified;
}
clear()
is much faster since it doesn't have to deal with all those extra method calls.
And as Atrey points out, c.contains(..)
increases the time complexity of removeAll
to O(n2) as opposed to clear
's O(n).
Type List vs type ArrayList in Java
Almost always List
is preferred over ArrayList
because, for instance, List
can be translated into a LinkedList
without affecting the rest of the codebase.
If one used ArrayList
instead of List
, it's hard to change the ArrayList
implementation into a LinkedList
one because ArrayList
specific methods have been used in the codebase that would also require restructuring.
You can read about the List
implementations here.
You may start with an ArrayList
, but soon after discover that another implementation is the more appropriate choice.
Related Topics
Varying Behavior for Possible Loss of Precision
Swing on Osx: How to Trap Command-Q
Spring Boot 2.0.X Disable Security for Certain Profile
Java Socket/Serialization, Object Won't Update
Parsing Xml with Regex in Java
Java 8 Date and Time: Parse Iso 8601 String Without Colon in Offset
Run a Single Test Method with Maven
Jax-Rs - How to Return JSON and Http Status Code Together
Why Does This Go into an Infinite Loop
Difference Between List, List<>, List<T>, List<E>, and List<Object>
Is the Buildsessionfactory() Configuration Method Deprecated in Hibernate
Best Way to Encode Text Data for Xml in Java
Parsing Xml with Regex in Java
Layering Multiple Glasspane's in a Root Container
Ignoring Ssl Certificate in Apache Httpclient 4.3