is using Any as collection type consume less memory than using concrete type?
suppose
val list1 = listOf<Any>("ABC", "DEF", "GHI", "JKL", "MNO")
val list2 = listOf<String>("ABC", "DEF", "GHI", "JKL", "MNO")
i wonder if list1
consume less memory than list2
since String
type allocates memory to store its properties (e.g size
)
So, is it better to use list1
if i dont use any String
type function?
EDIT
what if i want to use other type in the collection?
list = listOf<Any>("ABC", 123, 12.34)
is it more efficient than
list = listOf<String>("ABC", "123", "12.34")
EDIT 2
thanks to @João Dias and @gidds
as @gidds says :
the list does not directly contain String objects, or Any objects — it contains references.
And a String reference is exactly the same size as an Any reference or a reference of any other type.
So, The List<String>
and List<Any>
are the exactly the same because of the Type Erasure --which pointed out by @João Dias-- with a difference of compile-time & runtime type
but, does it mean that
val list1 = listOf<Any>("ABC", "DEF", "GHI")
and
val list2 = listOf<String>("ABC", "DEF", "GHI")
is consuming the same memory as
val list3 = listOf<List<List<List<String>>>>(
listOf(listOf(ListOf("ABC"))),
listOf(listOf(ListOf("DEF"))),
listOf(listOf(ListOf("GHI")))
)
AFAIK, String
is basically collections of Char
. A String
contains a reference to the Char
. And since everything is an object in Kotlin, then every Char
inside the String
should contain a reference to the value in the heap, am i correct up to here?
if thats the case, doesnt it make sense that List<String>
consume more memory than List<Any>
because List<String>
is having more than 1 reference.
A point not addressed so far is that the list does not directly contain String
objects, or Any
objects — it contains references.
And a String
reference is exactly the same size as an Any
reference or a reference of any other type. (That size depends on the internals of the JVM running the code; it might be 4 or 8 bytes. See these questions.)
Of course, the objects being referred to will also take up their own space in the heap; but that will be the same in both cases.
EDITED TO ADD:
The internal details of how List
and String
are implemented is irrelevant to the original question. (Which is good, coz they vary between implementations.) JVM languages (such as Kotlin) have only two kinds of value: primitives (Int
, Short
, Long
, Byte
, Char
, Double
, Float
, Boolean
), and references (to an object or an array).
So any collection, if it's not a collection of primitives, is a collection of references. That applies to all List
implementations. So your list1
and list2
objects will be exactly the same size, depending only on the number of references they hold (or can hold), not on what's in those references.
If you want a deeper picture, list1
is a reference, pointing to an object which implements the List
interface. There are many different implementations, and I don't know off-hand which one Kotlin will pick (and again, that might change between versions), but say for example it's an ArrayList
. That has at least two properties: a size (which is probably an Int
), and a reference to an array which holds the references to the items in the list. (The array will usually be bigger than the current size of the list, so that you can add some more items without having to re-allocate the array each time; the current size of the array is known as the list's capacity.) If those items are String
s, then the exact internal representation depends on the JVM version, but it might be an object with at least three properties: an array of Char
, an Int
giving the start index of the string within the array, and another Int
giving either the length.
But as I said, the details change over time and between JVM versions. What doesn't change is that List
is a collection of references, and the size of a reference doesn't depend on its type. So a list of String
references will (all other things being equal) take exactly the same space as a list of Any
references to those same strings.
(And, as has been mentioned elsewhere, due to type erasure at runtime the JVM has no concept of type parameters, and so the objects will in fact be identical.)
Of course, the ‘deep size’ (the overall heap space taken up by the list and the objects it contains) will depend upon the size of those objects — but in the case we're discussing, those are the exact same String
objects, so there's no difference in size there either.