Basic question
Consider this object:
Person alice = new Person("Alice", 0);
It's added to two ArrayLists:
ArrayList<Person> foo = new ArrayList<Person>();
ArrayList<Person> bar = new ArrayList<Person>();
foo.add(alice);
bar.add(alice);
At this point, are there three Person objects in heap memory (alice
plus one in each ArrayList)? Or is there one Person object in memory along with three references (pointers) to it?
Motivation for/more involved question
A Person object has two fields, a String and an int. Say I have many Person objects, and I want to have them all sorted in two different ways at different times (sometimes by their Strings alphabetically, sometimes by their ints numerically).
It seems this can be done in two ways:
Have one container, like an ArrayList, of the objects and sort it on demand whenever I want to change the sorting scheme
Have two containers, one which sorts Persons by their Strings alphabetically and one which sorts by their ints numerically
The first way is time inefficient but space efficient.
The second way is time efficient but space inefficient (say Person objects are very large).
In languages like C++, doing this efficiently in time and space would entail the second way but with multiple containers of pointers to a single collection of Person objects. Because this is difficult, people often recommend things like Boost's multi_index_container, which does exactly this. In Java, I've seen people elide this complexity, something that seems possible because all Java objects are behind pointer-like references at all times.
Are they correct in doing so? In Java, is doing things the second way in a space-efficient manner as simple as having multiple containers with redundant references to the same objects?
Bonus question
Is this true or untrue in other languages, like JavaScript, Python, Ruby, C#, Go, Rust, etc.?