I'm creating two Arraylist
s, 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 fromList
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 theList
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 anArrayList
or a subtype ofArrayList
. Therefore it knows that that object will support all of the methods defined byArrayList
and/or its superclasses. That includesArrayList.trimToSize()
.For
list
, the compiler only knows that the object in the variable is some class that implements theList
interface. So it only knows that it has methods in theList
API. The compiler doesn't know if the object is actually anArrayList
, or aLinkedList
, or aCopyOnWriteList
or any other class that implementsList
. So methods that are NOT in theList
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 aList
."