11

I am getting out of memory error with just 50000 objects.

I checked computeIfAbsent implementation but unfortunately did not find any thing peculiar.

My machine configuration is 16 GB ram and core I7.

public class Test {

    public static void main(String[] args) {
        int count = 50000;
        List<ListObject> list = new ArrayList();
        for (int i = 0; i < count; i++) {
            int key = ThreadLocalRandom.current().nextInt(100000);
            int value = ThreadLocalRandom.current().nextInt(1000000);
            list.add(new ListObject(key, value));
        }
        Map<Integer, List<Integer>> map = new HashMap();
        for (ListObject a : list) {
            map.computeIfAbsent(a.getKey(), ArrayList::new);
        }
        System.out.println("Done");

    }

and my ListObject is below:

class ListObject {
    public ListObject(int key, int value) {
        this.key = key;
        this.value = value;
    }

    public int getKey() {
        return key;
    }

    public void setKey(int key) {
        this.key = key;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    private int key;
    private int value;

}

Can some one please help me understand this behavior.

T-Bag
  • 10,916
  • 3
  • 54
  • 118
  • Any method can throw an OOM error – Michael Dec 09 '19 at 09:15
  • @Michael I reproduced this too. The curious thing is that if you replace `computeIfAbsent` with `put`, the exception goes away. Wonder whether this has to do with the implementation... – ernest_k Dec 09 '19 at 09:21
  • 1
    `List list = new ArrayList<>(count);` You forgot the diamond operator `<>`. For better speed and memory usage already reserve space for `count` items too. The same with: `new HashMap<>(count)` – Joop Eggen Dec 09 '19 at 09:22
  • @ernest_k - I checked the implementation , to be frank did not get much out of that. – T-Bag Dec 09 '19 at 09:24
  • Wow... Thanks @Holger. Interesting how hard it is to see the obvious :) – ernest_k Dec 09 '19 at 09:26

1 Answers1

18

The erroneous part is this:

ArrayList::new

What you don't realise is that this is not inferred to

() -> new ArrayList<>()

but to

key -> new ArrayList<>(key)

i.e. every list is created with a random size from 0 to 100000. Worst case that's 5 billion.

Michael
  • 41,989
  • 11
  • 82
  • 128