List.Clear() VS List = New Arraylist<Integer>();

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



Leave a reply



Submit