Search code examples
javalistif-statement

Does (COND1 || COND2) skip checking COND2 if COND1 is true?


I want to store top 3 values from some source in a List. The simplified example is here:

import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        List<Integer> top3 = new ArrayList<>();

        while (true) {
            Integer newInt = Integer.valueOf(sc.nextInt());

            for (int i = 0; i < 3 && i <= top3.size(); i++) {
                if (i == top3.size() || newInt.compareTo(top3.get(i)) > 0) {
                    newInt = top3.set(i, newInt);
                }
            }

            System.out.println(top3.toString());
        }
    }
}

But the problem is that the program throws an java.lang.IndexOutOfBoundsException. So here is the question: isn't || operator supposed to skip checking conditions after it reaches the first one? Because if it would, I would not get an error.

EDIT:

As I pointed in my answer, the problem was in ".set()" method, as I expected it to append the List if the method is applied to the end of it.


Solution

  • The answer is that (COND1 || COND2) in fact stops checking if COND1 is already true.

    I've found out that the exception is thrown by the set() method, not by get() method, which proves that the answer for the question is "yes".

    The problem is that I expected top3.set(i, newInt) to just append top3 with newInt when i reaches top3.size(). But according to the documentation, this method just throws the mentioned java.lang.IndexOutOfBoundsException if so.

    I solved the problem like this:

    import java.util.List;
    import java.util.ArrayList;
    import java.util.Scanner;
    
    public class Main {
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            List<Integer> top3 = new ArrayList<Integer>();
    
            while (true) {
                Integer newInt = Integer.valueOf(sc.nextInt());
    
                for (int i = 0; i < 3; i++) {
                    if (i == top3.size()) {
                        top3.add(newInt);
                        break;
                    } else if (newInt.compareTo(top3.get(i)) > 0) {
                        newInt = top3.set(i, newInt);
                    }
                }
    
                System.out.println(top3.toString());
            }
        }
    }