Question: I have written a java program in which I am supposed to know that if the two nested for loops can finish their execution in 4 seconds or not If they finish their execution in 4 seconds then the program should continue else break the loop. I have three list A ,B and C and I am performing some operation and adding it to the list B. Even for the small inputs to the list A and C like 3, 6, 8, 4, My program throws `run out of memory error`  

I am using one outer for loop for calculating time. If two for loops couldn't finish their execution in 4 seconds the loop should be terminate. I am using one count variable to keep track of the for loop execution even if for loop finished their execution before 4 seconds i am terminating the outer for loop.  

Here is my **code** :

```
while(!(A.isEmpty())){
    ArrayList<Long> B = new ArrayList<>();
    for(long start = System.currentTimeMillis() ; start < System.currentTimeMillis() + 4 * 1000 ; ){
        for(long i : A){
            for(long j : C){
                if(i!=j){
                    B.add(Math.abs(i-j));
                }
            }
            count++;
            if(count==A.size());
                break;
        }
    }
}

```

What is wrong with this code ? How should I make it correct ?  

Thank you.

Answer: 
I think this design isn't really robust. Instead of calling the time function within that loop, I think you could be looking into using two threads here:

1. Thread A kicks of thread B, and waits for *n* seconds
2. Thread B does the computation
3. When thread A wakes up, it simply checks if the computation is done

Alternatively, your main thread kicks of A and B; and A just comes back and tells you: time to check the results of B now.

And for your real problem; I guess *one* contributor is here:

```
B.add(Math.abs(i-j));

```

You see B (really bad name for a **list** of numbers btw!) taks Long objects. So that little call there creates at least one Long object per iteration. And you iterate over A and C. Without any sleeps or delays there. This means that your code is doing **nothing** else but iterating loops and creating new objects to fill that B list.

Now: how many loop iterations do you think you will see in 4 seconds? Enough to create millions and millions of objects?! And then: a dynamically growing list is nice, but you understand what it **means** when an ArrayList constantly goes over its capacity and needs to grow?! You understand that this means creation of **new** arrays, and copying around of all values?!

What I am saying is: look carefully how much work is really going on there; and how much (un)boxing of primitive/reference long/Long you got in your code.

One (maybe easy way) to test these ideas: change your code from using List of Longs into using fixed arrays with long values. That will have a nice side effect - it will force you think *upfront* about how many array slots you actually want to create. In your solution, you just keep looping and adding new objects (as said; leading to **constant** re-capacity increase operations for your B list).
You Have an infinite loop, `while(!(A.isEmpty))` will always be true because inside of your for loops you are never removing any elements from A. This will cause you to add an infinite amount of elements to B becuase of `B.add(Math.abs(i-j));`