0

Why can't I save ArrayList size as a variable?

public static ArrayList <Integer > merge(ArrayList <Integer > list1,
                                          ArrayList <Integer > list2 ) {

    if (list1.size() >= list2.size()) {
        int maxSize = list1.size(); 
    } else {
        int maxSize = list2.size();
    }

    for (int i = 0; i < maxSize; i++) {

        if (i <= list2.size()) {
            int nextInList2 = list2.get(i);
            list1.add(i, nextInList2);
        }
    }
    System.out.println(list1);
    return (list1);

in: int maxSize = list1.size(); I assume that it's not saving the variable as I want to.

I assume that

list1.size()

is an integer

Reg
  • 10,717
  • 6
  • 37
  • 54
Ida
  • 31
  • 2
  • 3
    of course you can save them, and you are doing so, but you declare those ints in those if-else blocks, meaning they don't exist outside of the scope of them. declare the variable before the if, and just assign the value in the if-else blocks to solve your issues – Stultuske Nov 16 '22 at 14:15
  • You define the variable inside curly braces. It does not exist outside of those braces. That is called the scope of the variable. – f1sh Nov 16 '22 at 14:15
  • 1
    You need to understand a lot more about scopes. Currently your variable maxSize is only working in the scope of if. – Gatusko Nov 16 '22 at 14:16
  • You are misinterpreting the error you get. Of course you can save the size in an in t variable and you do that at 2 places in your code. Your error is however that you try to use those maxSize variables outside their scope. See [What is 'scope' in Java?](https://stackoverflow.com/questions/38177140/what-is-scope-in-java) – OH GOD SPIDERS Nov 16 '22 at 14:16
  • https://docs.oracle.com/javase/tutorial/java/TOC.html – Basil Bourque Nov 17 '22 at 02:11

3 Answers3

6

TLDR;

Just declare maxSize above the if and else statements. And Bob's your uncle. Then you can use maxSize everywhere in your method/function.

Solution

This is a scope problem. To solve your issue, declare the variable (maxSize) outside the brackets of the if-else statement. When you declare them in the brackets, you will only be able to use them within them (Scope).

int maxSize = 0;
if (list1.size() >= list2.size()) {
    maxSize = list1.size(); 
} else {
    maxSize = list2.size();
}

// Now maxSize can be used as you wish :)
for (int i = 0; i < maxSize; i++) { ...

Notes:

  • As @berse2212 pointed out if you add or remove items to your array, you need to update your maxSize again.
  • Also, like with @so-random-dude showed, you can replace the if else statement with this gem :

int maxSize = Math.max(list1.size(), list2.size());

What on earth is Scope about?

Scope defines the lifetime of a variable. Let's take a deeper look at your example. For simplicity, let us ignore the else.

...
    if (list1.size() >= list2.size()) {
        // Start If statement's Scope. 
        int maxSize = list1.size(); // Add maxSize to scope
        // Max Size is in scope and can be used as you wish
        // End the scope, in other words, maxSize does not exist anymore.
    }

// maxSize has left the building, and the compiler does not know about it.
... 

This is just a small example. But you can find more (and better) information here or here

Hope this helps

Reg
  • 10,717
  • 6
  • 37
  • 54
  • 1
    Just a small addition - be careful if you store the size in a Variable because it does not get updated when the size of the ArrayList increases or decreases. – berse2212 Nov 16 '22 at 14:32
  • 1
    @berse2212 Good point, I added to the answer for completeness :) – Reg Nov 16 '22 at 14:37
  • Is there any benefit to initializing maxSize to 0? Yes, I know, "All variables must be initialized!!!!!" But you *are* initializing maxSize, in row 3 or 5. AFAICT the only effect this dummy-initialization has is suppressing the compiler warning if you forget the real initialization in one of the branches. – Sören Nov 16 '22 at 17:10
  • 1
    Hi @Sören! Maybe consider asking a question or searching SO on this one. There is a lot to unpack in your simple question, but let me try. First, Not *All* variables should be initialized; only local ones (Fields or instance-level variables will be set to a default value). Secondly, it is not a compiler warning, it is a compiler error when a local variable is not initiated(code will not compile). Finally, in the example above, there will be no error if not initiated, as the compiler is smart enough to evaluate if-else statements. Change it to an if-else-if then there will be a compiler error. – Reg Nov 17 '22 at 08:23
  • Finally - I assigned it to 0, as the main focus of the question is regarding "the scope" and not initialising variables. It is a matter of preference, not a matter of any advantages. – Reg Nov 17 '22 at 08:25
2

As others have already pointed out, it's indeed a scope problem. The variable maxSize is born and died with in the if block (and another one with the same name again in the else block - See, compiler didn't complain even when you had 2 reference variables with the same name, one in the if block and another one in the else block - Because compiler knows that the maxSize that you created in the if is out-of-scope for else ).

What Reg given is the correct solution

The following is just a different, concise way to solve the problem

You can use ternary operator like this

int maxSize = (list1.size() >= list2.size()) ? list1.size() : list2.size();

Or even better

int maxSize = Math.max(list1.size(), list2.size());

Also, next time, when you ask the question, try to isolate the problem and eliminate all the unnecessary details. For example, in this case, if you have tried

if (true) {
        int maxSize = 1; 
    } else {
        int maxSize = 2;
    }

System.out.println(maxSize); // Compiler will scream at you.

you could have avoided talking about arrayList and come to the crux of the problem. See, arrayList was just a red herring, Probably you could have figured it all by yourself.

so-random-dude
  • 15,277
  • 10
  • 68
  • 113
0

The variable is scoped to the if, declare it outside to bring it to scope:

int maxSize;
if (condition) {
   maxSize = ... 
} else {
   maxSize = ... 
}
// now can be used in the for
for (int i = 0; i < maxSize; i++ ) {
}

As pointed in another answer, you can also use the ternary operator

int maxSize = list1.size() >= list2.size() ? list1.size() : list2.size(); 
for (int i = 0; i < maxSize; i++ ) {
}

Just be aware to balance readability.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569