Say I have the following stream:
List<Other> list = Stream
.of(
new MyObject(),
new MyObject()
)
.map(this::mapToOther)
.collect(toList())
;
So after this is executed, I will certainly get a list of Other
in memory, but I wonder whether the source objects (i.e. MyObject
) are still "alive" in memory (I mean not yet garbage collectable)?
2 Answers 2
You did not say what ́mapToOther` should or should not do.
So assume:
mapToOther has the signature
Other mapToOther(MyObject obj)
, and transformsobj
of type MyObject to a new object of typeOther
it does not keep a reference to
obj
somewhere else (maybe in some cache)it does not put a reference to
obj
into the newly created ́Other` objectthe implementation of the Stream classes is quite sane and takes cares not to create memory leaks
then the source objects are "garbage collectable" right after the assignment. If one of the above assumptions is violated, then the MyObject instances will continue to "live".
To answer your comment:
as the stream goes through each source object, would each of them be garbage collectable right after it completes the map but before all completed the map
This ultimately depends on the underlying implementation of Stream.of
and map
. The Stream documentation discourages multiple consumptions of a stream, hence there is no mandatory reason for the elements to be kept in scope right after they were processed. On the other hand, Stream.of
uses varargs, so all of the instances of MyObject
are first created and then put into an array internally before .of
is executed. The most straightforward implementation of of
and map
might simply keep the elements in that array internally. So I would usually expect the elements are not garbage collectable before the assignment is completed.
-
Thank you and especially for addressing my comment as well. By "right after the assignment", I believe you mean after the
map
right? Not necessarily after thecollect
, no?user1589188– user15891882024年01月24日 02:10:42 +00:00Commented Jan 24, 2024 at 2:10 -
1@user1589188; no, I meant "right after the full assignment." - then it is sure the objects are garbage collectable. Assuming the "map" for all objects is completed before the "collect" operation starts is a misunderstanding of what happens here. See stackoverflow.com/q/29915591 for a better understanding. It may happen that the processed subset of the objects are GC-able already in the middle of the collect operation, but it ulitmatemaly depends on the underlying implementation.Doc Brown– Doc Brown2024年01月24日 06:19:05 +00:00Commented Jan 24, 2024 at 6:19
As far as garbage collection goes it does what this does:
Other other = mapToOther(new MyObject());
That is, if mapToOther()
leaves other
holding a hard reference to your MyObject
instance they will live and die together. If not the MyObject
instance is eligible for garbage collection when you hit the semicolon. These things have been called nameless temporary objects or anonymous objects. Not every object gets directly associated with an identifier like a variable. But they can live forever in an object graph. That's one of the reasons circular references are such a bad thing.
list
is assigned, everything but it's content is garbage collectible. If the question is about a moment before the second call tomapToOther
the situation is not that trivial.map
but before all completed themap
?