-1

If I have the following:

List<String> list = new ArrayList<>(Arrays.asList("a","b","c"));

and call:

System.out.println(list.size());

It will print 3 as expected.

The size() method's code is just return size; where size is a private int.

So I'm wondering where it's actually setting that size variable.

I see it's calling the constructor public ArrayList(Collection<? extends E> c), which is fine, but when I debug into there, and hover over c, it already says size = 3.

So is it something in Collection<? extends E> c that's setting it to 3, before it gets to the ArrayList constructor?

achAmháin
  • 4,176
  • 4
  • 17
  • 40
  • Are you talking about http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java#l169? – Micha Wiedenmann Oct 19 '18 at 13:33
  • What do you mean by `c == 3`? It's a Collection and not an int. – Murat Karagöz Oct 19 '18 at 13:34
  • Wow, heavy downvotes. @MuratKaragöz when I debug to that constructor, and hover over `c`, it says `size = 3`. I thought this was a valid question. – achAmháin Oct 19 '18 at 13:40
  • @achAmháin That's a feature of your IDE showing the size. – Murat Karagöz Oct 19 '18 at 13:42
  • 2
    *Wow, heavy downvotes* - also heavy upvotes. I would be content with a balance of 0 for a question you can answer simply by looking at the source – Tim Oct 19 '18 at 13:43
  • @TimCastelijns fair enough. I did look at the source code, but unfortunately I mis-read that specific line. But it answers my question. – achAmháin Oct 19 '18 at 13:47
  • 1
    @achAmháin maybe some IDE feature confused you? Something like the image I posted in my answer. It has happened to my from time to time ;) – lealceldeiro Oct 19 '18 at 14:00

4 Answers4

3

(...) I'm wondering where it's actually setting that size variable

You called this constructor of ArrayList in which source code we can see size = elementData.length;:

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length; // <-- HERE
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
}

So, once it is called size() (source code) that value is already set.


when I debug into there, and hover over c, it already says size = 3

If you are referring to something like the image below... I think it might be some IDE feature (like in my case with IntelliJ IDEA) where it can infer the specific type of c (List) and compute its size.

enter image description here


(...) is it something in Collection<? extends E> c that's setting it to 3, before it gets to the ArrayList constructor?

Remember Arrays.asList returns a List which is taken by the ArrayList's constructor as a Collection which also has a size method. IDEs can use that for calculating the size value.


PS: The source code might slightly differ from specific jdk version to another version.

lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
1

It says it's already 3 because that is the size of the Arrays.asList("a","b","c") you pass as argument to new ArrayList<>(Arrays.asList("a","b","c"));.

From sources:

public ArrayList(Collection<? extends E> c) {
    // c is already instantiated here 
    elementData = c.toArray();
    // ...
}
1

It happens when you initialise the new ArrayList; in the constructor, you can see the size of the list is set to the size of the array you pass in:

/**
 * Constructs a list containing the elements of the specified
 * collection, in the order they are returned by the collection's
 * iterator.
 *
 * @param c the collection whose elements are to be placed into this list
 * @throws NullPointerException if the specified collection is null
 */
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

so specifically if ((size = elementData.length) != 0) sets the size (the private field you were talking about) to the length of the array passed into the constructor.

Luke Garrigan
  • 4,571
  • 1
  • 21
  • 29
0

Here, the size is set on the next line in the constructor of the ArrayList.

if ((size = elementData.length) != 0) {

Details are well explained in this other SO thread Details

keybored
  • 129
  • 2