Home > Mobile >  List Interface and ArrayList Class: ensureCapacity() and trimToSize() methods
List Interface and ArrayList Class: ensureCapacity() and trimToSize() methods

Time:05-26

I'm creating two Arraylists, and then I want to apply ensureCapacity() and trimToSize(), but

ArrayList<String> arrayList = new ArrayList<>();
arrayList.trimToSize();
arrayList.ensureCapacity(100);

List<String> list = new ArrayList<>();
list.trimToSize();
list.ensureCapacity(100);

when I'm creating Arraylist from Class, I can do that.

And when I'm creating Arraylist using List Interface, I can't.

Can you tell me please why so?

I've looked into Javadoc and I see that only ArrayList has ensureCapacity() and trimToSize() methods.

But why I can't use them on my ArrayList when I create it from List interface?

CodePudding user response:

Both methods trimToSize() and ensureCapacity() are available only in the ArrayList class.

There's no such methods in the List interface.

The reason for that: these methods are meant to change the size of the underlying array. trimToSize() creates a new array of length equal to the size of the list, and ensureCapacity() will create a new underlying array of the given length.

These methods don't make sens for the LinkedList which isn't backed by an array, therefore they are not declared in the List interface.

It's also worth to point out that trimToSize() should be used with caution because you can create a cycle or continuous growth and trimming and ArrayList would perform very badly.

Consider this: about 50% of elements were removed from your ArrayList and you what to release this unoccupied heap space with trimToSize(). A new underlying array twice smaller would be created and all existing elements would be copied into it. But with the next added item ArrayList would become two times bigger again (it means a new array should be allocated in memory and all elements should be copied into it). Doesn't sound very performant.

In general, trimToSize() is something that might be worth knowing about because it's a part of the JDK, and because someone might ask you about it, for instance, during an interview. But you would never use it.

But why I can't use them on my ArrayList when I create it from List interface?

When a variable is of type List you can use only methods that are declared in the list interface. The type of reference defines how you can interact with the object. A reference isn't an object itself. And it does not change the object anyhow, your ArrayList still remains to be an ArrayList. A reference type List defines a way to interact with the object (which is still an ArrayList).

In order to access its methods that are not defined in the List interface, you can cast it:

List<String> list = new ArrayList<>();

ArrayList<String> list2 = (ArrayList) list;
list2.trimToSize();
list2.ensureCapacity(100);

But note that this casting is unsafe, it will succeed only if variable list points to an ArrayList and not LinkedList. And as I've said earlier, it's OK to play with these methods, but you would hardly need them in the future.

CodePudding user response:

I think there is something important you are missing about Java. You say:

When I'm creating ArrayList from the class, I can do that.

And when I'm creating ArrayList using the List interface, I can't.

This is not correct. In both cases you are creating an ArrayList using new ArrayList<>(). The two objects are being created in exactly the same way.

The difference between the two versions is in what happens after the ArrayList objects are created.

ArrayList<String> arrayList = new ArrayList<>();

assigns the new object to a variable whose type is ArrayList<String>, but

List<String> list = new ArrayList<>();

assigns the new object to a variable whose type is List<String>.

The difference is in the types of the respective variables ... not the types of the objects.

  • For arrayList, the compiler knows that the object that the variable refers to will be an ArrayList or a subtype of ArrayList. Therefore it knows that that object will support all of the methods defined by ArrayList and/or its superclasses. That includes ArrayList.trimToSize().

  • For list, the compiler only knows that the object in the variable is some class that implements the List interface. So it only knows that it has methods in the List API. The compiler doesn't know if the object is actually an ArrayList, or a LinkedList, or a CopyOnWriteList or any other class that implements List. So methods that are NOT in the List API cannot be applied to it.

    Hence the compilation errors.


But why I can't use them on my ArrayList when I create it from List interface?

(You didn't ... see above.)

Because you assign the ArrayList object to a List variable, you are saying to the compiler:

"Forget that this is an ArrayList. Think of it as a List."

  • Related