What if Java Consistently Used Intention Revealing Names for Inner Classes?
The pain of reading and understanding a class without a name.
What if Java Consistently Used Intention Revealing Names for Inner Classes?
The pain of reading and understanding a class without a name.
Photo by Brett Jordan on Unsplash
Jmap and JOL are your friends
I’ve been teaching developers how to use both [jmap](https://donraab.medium.com/i-used-five-command-line-java-tools-this-week-and-i-feel-good-a07531fefb02?source=friends_link&sk=ec2cc3fb5f20fb7ae30b57f994601234) and Java Object Layout (JOL) to understand the cost of memory for types in Java for quite a while now. In the case of jmap, I have been teaching how to use this very useful command line tool for over two decades. JOL I learned about a few years ago. I believe it has been around as a tool since late 2013. JOL is like a microscope (you can look at a single instance or class), and jmap is alike a full body x-ray image (you see all the instances on your heap). Java developers should learn and keep both tools handy to understand the impact of implementation decisions on their Java heaps.
JOL and jmap can help you understand what is taking up space on your Java heap. How well they can do this is dependent on the names of the types provided by the libraries you use. If the names of your types are not explicit and instead are determined by anonymous inner classes, you’re going to have to go digging through source code to figure out what is meant by someClass$1, someClass$2, someClass$3, etc.
When your friends can’t help you
Java Collections and Stream could be more helpful to developers by using explicit names for inner classes instead of relying on anonymous inner classes. Using anonymous inner classes pushes the pain of discovering the location of classes on the developer. I encountered this pain this evening. I stared at output from JOL wondering “What is java.util.Collections$2?” I had never seen this type before. Do you know what it is? I certainly didn’t. Now I do. But I will forget what it means, and I can’t easily look it up, so I am writing it down here.
Do you know what java.util.stream.ReferencePipeline$2 is? What about java.util.stream.ReferencePipeline$3? What about java.util.stream.ReferencePipeline$5? What about java.util.stream.ReferencePipeline$Head?
Ok, to be fair, the last one has an explicit name (java.util.stream.ReferencePipeline$Head), but my guess is that most Java developers will probably have no idea what this type is or what it is used for. Many Java developers may not know what the type ReferencePipeline is used for in Java. If you already know it is THE implementation of Stream in the JDK, well done!
But what is java.util.Collections$2 and where does it come from?
I’m going to share two parameterized test methods I ran an experiment with along with their JOL output results, and see if you can guess what the types in the JOL output are. If you can’t figure out what java.util.Collections$2 is on your own, you can find out later in this blog.
In order to run the code examples in this blog, I used Java 25 with Compact Object Headers (COH) enabled and Java Object Layout (JOL) 0.17. The copyable text JVM setting for COH and latest Maven dependency info for JOL can be found in the following blog.

Setting to enable Compact Object Headers on Java 25

Latest Maven dependency Info for Java Object Layout (JOL)
Can you figure out the JDK types using JOL?
I have written a parameterized JUnit test that will use List instances from size 0 to 9, containing String representations of the indexes (e.g. List.of(), List.of(“1”), List.of(“1”, “2”), etc. I am using the following code from JOL’s GraphLayout class to output the footprint of a single object.
GraphLayout.parseInstance(mapToLong).toFootprint()
Here’s the source code I used for the parameterized test:
@ParameterizedTest
@MethodSource("jdkListProvider")
public void javaTypesForImmutableListAndStream(List<String> list)
{
var stream = list.stream();
var filter = stream.filter(i -> true);
var map = filter.map(Object::toString);
var mapToLong = map.mapToLong(String::length);
IO.println(GraphLayout.parseInstance(mapToLong).toFootprint());
assertTrue(mapToLong.allMatch(each -> each == 1));
IO.println("** stream = " + stream.getClass().getTypeName());
IO.println("** filter = " + filter.getClass().getTypeName());
IO.println("** map = " + map.getClass().getTypeName());
IO.println("** mapToLong = " + mapToLong.getClass().getTypeName());
IO.println("** Size of -> " + list.getClass().getSimpleName() + " = " + list.size());
IO.println("=======================");
}
static Stream<Arguments> jdkListProvider()
{
// Returns a Stream of Arguments containing List.of() from size 0 to 9
// e.g. List.of(), List.of("1"), List.of("1", "2"), etc.
var list = Stream.concat(
Stream.of(Arguments.of(List.of())),
IntStream.range(2, 11)
.mapToObj(i -> IntStream.range(1, i))
.map(s -> s.mapToObj(Integer::toString))
.map(Stream::toList)
.map(List::copyOf)
.map(Arguments::of))
.collect(Collectors.toList());
Collections.shuffle(list);
return list.stream();
}
The output will be different each time, since I am shuffling the order of the List instances to make it harder to guess the size of a List you are looking at in the JOL output. Here is the output for one run. I show the JOL footprint for mapToLong which will wind up having references to everything that came before in its object graph. I made it easier to figure out the details of each run at the end, because it would be possibly too challenging and infuriating otherwise.
// JDK Types Run 1
java.util.stream.ReferencePipeline$5@53045c6cd footprint:
COUNT AVG SUM DESCRIPTION
5 16 80 [B
1 32 32 [Ljava.lang.Object;
5 24 120 java.lang.String
1 32 32 java.util.AbstractList$RandomAccessSpliterator
1 16 16 java.util.ImmutableCollections$ListN
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
20 520 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> ListN = 5
// JDK Types Run 2
java.util.stream.ReferencePipeline$5@1e097d59d footprint:
COUNT AVG SUM DESCRIPTION
7 16 112 [B
1 40 40 [Ljava.lang.Object;
7 24 168 java.lang.String
1 32 32 java.util.AbstractList$RandomAccessSpliterator
1 16 16 java.util.ImmutableCollections$ListN
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
24 608 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> ListN = 7
// JDK Types Run 3
java.util.stream.ReferencePipeline$5@e57b96dd footprint:
COUNT AVG SUM DESCRIPTION
9 16 144 [B
1 48 48 [Ljava.lang.Object;
9 24 216 java.lang.String
1 32 32 java.util.AbstractList$RandomAccessSpliterator
1 16 16 java.util.ImmutableCollections$ListN
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
28 696 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> ListN = 9
// JDK Types Run 4
java.util.stream.ReferencePipeline$5@3d3e5463d footprint:
COUNT AVG SUM DESCRIPTION
2 16 32 [B
2 24 48 java.lang.String
1 32 32 java.util.AbstractList$RandomAccessSpliterator
1 16 16 java.util.ImmutableCollections$List12
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
13 368 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> List12 = 2
// JDK Types Run 5
java.util.stream.ReferencePipeline$5@31c7528fd footprint:
COUNT AVG SUM DESCRIPTION
1 16 16 [B
1 24 24 java.lang.String
1 24 24 java.util.Collections$2
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
10 304 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> List12 = 1
// JDK Types Run 6
java.util.stream.ReferencePipeline$5@1b84f475d footprint:
COUNT AVG SUM DESCRIPTION
3 16 48 [B
1 24 24 [Ljava.lang.Object;
3 24 72 java.lang.String
1 32 32 java.util.AbstractList$RandomAccessSpliterator
1 16 16 java.util.ImmutableCollections$ListN
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
16 432 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> ListN = 3
// JDK Types Run 7
java.util.stream.ReferencePipeline$5@5812f68bd footprint:
COUNT AVG SUM DESCRIPTION
6 16 96 [B
1 40 40 [Ljava.lang.Object;
6 24 144 java.lang.String
1 32 32 java.util.AbstractList$RandomAccessSpliterator
1 16 16 java.util.ImmutableCollections$ListN
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
22 568 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> ListN = 6
// JDK Types Run 8
java.util.stream.ReferencePipeline$5@6d025197d footprint:
COUNT AVG SUM DESCRIPTION
4 16 64 [B
1 32 32 [Ljava.lang.Object;
4 24 96 java.lang.String
1 32 32 java.util.AbstractList$RandomAccessSpliterator
1 16 16 java.util.ImmutableCollections$ListN
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
18 480 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> ListN = 4
// JDK Types Run 9
java.util.stream.ReferencePipeline$5@3a4621bdd footprint:
COUNT AVG SUM DESCRIPTION
8 16 128 [B
1 48 48 [Ljava.lang.Object;
8 24 192 java.lang.String
1 32 32 java.util.AbstractList$RandomAccessSpliterator
1 16 16 java.util.ImmutableCollections$ListN
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
26 656 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> ListN = 8
// JDK Types Run 10
java.util.stream.ReferencePipeline$5@4f9a2c08d footprint:
COUNT AVG SUM DESCRIPTION
1 16 16 [Ljava.lang.Object;
1 32 32 java.util.AbstractList$RandomAccessSpliterator
1 16 16 java.util.ImmutableCollections$ListN
1 56 56 java.util.stream.ReferencePipeline$2
1 56 56 java.util.stream.ReferencePipeline$3
1 56 56 java.util.stream.ReferencePipeline$5
1 48 48 java.util.stream.ReferencePipeline$Head
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001273c00
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276000
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x0000100001276400
10 304 (total)
** stream = java.util.stream.ReferencePipeline$Head
** filter = java.util.stream.ReferencePipeline$2
** map = java.util.stream.ReferencePipeline$3
** mapToLong = java.util.stream.ReferencePipeline$5
** Size of -> ListN = 0
This is the order of the List parameters for this run according to the JUnit runner in IntelliJ.

The order of parameterized runs in JUnit for JDK Types
Here’s a link to the source code in a project in GitHub.
Can you figure out the Eclipse Collection types using JOL?
I have written a parameterized JUnit test that will use ImmutableList instances from size 0 to 9, containing String representations of the indexes (e.g. Lists.immutable.of(), Lists.immutable.of(“1”), Lists.immutable.of(“1”, “2”), etc. I am using the following code from JOL’s GraphLayout class to output the footprint of a single object.
GraphLayout.parseInstance(collectLong).toFootprint()
Here’s the source code I used for the parameterized test:
@ParameterizedTest
@MethodSource("ecImmutableListProvider")
public void eclipseCollectionTypesForImmutableListAndLazy(ImmutableList<String> list)
{
var lazy = list.asLazy();
var select = lazy.select(i -> true);
var collect = select.collect(Object::toString);
var collectLong = collect.collectLong(String::length);
IO.println(GraphLayout.parseInstance(collectLong).toFootprint());
assertTrue(collectLong.allSatisfy(each -> each == 1));
}
static Stream<Arguments> ecImmutableListProvider()
{
// Returns a Stream of Arguments containing Lists.immutable.of() from size 0 to 9
// e.g. Lists.immutable.of(), Lists.immutable.of("1"), Lists.immutable.of("1", "2"), etc.
return Lists.mutable.of(Arguments.of(Lists.immutable.of()))
.withAll(
IntInterval.oneTo(9)
.collect(IntInterval::oneTo)
.collect(v -> v.collect(Integer::toString))
.collect(Arguments::of))
.shuffleThis()
.stream();
}
I removed all of the helpful outputs that I had to use for JDK, to see if you can figure out the Eclipse Collections types and List size with only the JOL output to help you figure things out.
// Eclipse Collections Types Run 1
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@4bff7da0d footprint:
COUNT AVG SUM DESCRIPTION
9 16 144 [B
9 24 216 java.lang.String
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 48 48 org.eclipse.collections.impl.list.immutable.ImmutableNonupletonList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
26 504 (total)
// Eclipse Collections Types Run 2
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@39a8312fd footprint:
COUNT AVG SUM DESCRIPTION
8 16 128 [B
8 24 192 java.lang.String
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 40 40 org.eclipse.collections.impl.list.immutable.ImmutableOctupletonList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
24 456 (total)
// Eclipse Collections Types Run 3
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@674bd420d footprint:
COUNT AVG SUM DESCRIPTION
1 16 16 [B
1 24 24 java.lang.String
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 16 16 org.eclipse.collections.impl.list.immutable.ImmutableSingletonList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
10 152 (total)
// Eclipse Collections Types Run 4
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@70a36a66d footprint:
COUNT AVG SUM DESCRIPTION
4 16 64 [B
4 24 96 java.lang.String
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 24 24 org.eclipse.collections.impl.list.immutable.ImmutableQuadrupletonList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
16 280 (total)
// Eclipse Collections Types Run 5
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@1d131e1bd footprint:
COUNT AVG SUM DESCRIPTION
7 16 112 [B
7 24 168 java.lang.String
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 40 40 org.eclipse.collections.impl.list.immutable.ImmutableSeptupletonList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
22 416 (total)
// Eclipse Collections Types Run 6
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@56303b57d footprint:
COUNT AVG SUM DESCRIPTION
6 16 96 [B
6 24 144 java.lang.String
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 32 32 org.eclipse.collections.impl.list.immutable.ImmutableSextupletonList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
20 368 (total)
// Eclipse Collections Types Run 7
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@3724af13d footprint:
COUNT AVG SUM DESCRIPTION
5 16 80 [B
5 24 120 java.lang.String
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 32 32 org.eclipse.collections.impl.list.immutable.ImmutableQuintupletonList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
18 328 (total)
// Eclipse Collections Types Run 8
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@7e7b159bd footprint:
COUNT AVG SUM DESCRIPTION
2 16 32 [B
2 24 48 java.lang.String
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 16 16 org.eclipse.collections.impl.list.immutable.ImmutableDoubletonList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
12 192 (total)
// Eclipse Collections Types Run 9
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@40dff0b7d footprint:
COUNT AVG SUM DESCRIPTION
3 16 48 [B
3 24 72 java.lang.String
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 24 24 org.eclipse.collections.impl.list.immutable.ImmutableTripletonList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
14 240 (total)
// Eclipse Collections Types Run 10
org.eclipse.collections.impl.lazy.primitive.CollectLongIterable@7e8dcdaad footprint:
COUNT AVG SUM DESCRIPTION
1 16 16 org.eclipse.collections.impl.lazy.CollectIterable
1 16 16 org.eclipse.collections.impl.lazy.SelectIterable
1 24 24 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable
1 16 16 org.eclipse.collections.impl.lazy.primitive.CollectLongIterable$LongFunctionToProcedure
1 8 8 org.eclipse.collections.impl.list.immutable.ImmutableEmptyList
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012ab400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b1400
1 8 8 refactortoec.generation.StreamLazyIterableMemoryTest$$Lambda/0x000007f0012b2c00
8 104 (total)
This is the order of the List parameters for this run according to the JUnit runner in IntelliJ.

The order of parameterized runs in JUnit for Eclipse Collections Types
Here’s a link to the source code in GitHub.
What is java.util.Collections$2 in the JDK output?
Nothing in the sample code I provided can help us discover what java.util.Collections$2 represents directly. There is a hint, if we look at the size that this type shows up in, which is size 1. The type of List for this size is List12. Do you pronounce this type as List Twelve, or List One or Two? I think ListOneOrTwo might have been a more intention revealing name. At least I wouldn’t have read it as “List Twelve” the first time I saw this type in JOL or jmap output.
Now we have to look on the type List12 for something special about size one. Found it.

The spliterator implementation in List12
Now if you’re wondering why Collections.singletonSpliterator(e0) results in a type named java.util.Collections$2, welcome to the club.

The beginning of the anonymous inner class returned by Collections.singletonSpliterator()
This doesn’t immediately explain why the List12 instance has mysteriously disappeared from the JOL output. We can reason about why this happens from the code in the spliterator() method above. A Stream will hold onto a Spliterator. A Spliterator like RandomAccessSpliterator will hold onto the List it is for as seen below.

RandomAccessSpliterator keeps a reference to the List it is for
The Collections.singletonSpliterator() instead holds onto the single element, which in this particular case was the String -> “1”. We don’t see a variable declaration inside of the anonymous inner class above, but if we look a little farther down the code, we will see there is a capture of the element reference in the anonymous inner class, which has the effect of creating a field in the type.

See the parameter element captured in the tryAdvance method, where is show as italicized
I would propose a more helpful name for the anonymous inner class returned by singletonSpliterator could be SingletonSpliterator.
Why don’t some of these types have names?
I don’t know the answer to this, but I hope it helps to ask. There are reasons why there are only List12 and ListN types in the JDK, and it has to do with megamorphism impacts on performance. I wrote a bit about this in the following blog.
This doesn’t help explain why there are not named types inside of ReferencePipeline for filter, map, mapToLong and other kind of pipeline types. We can see all of the anonymous types more easily by looking at all the subtypes of ReferencePipeline.

ReferencePipeline subtypes
If we go up one level to the Stream interface, this is what the hierarchy looks like.

Stream subtypes
If we compare this to LazyIterable subtypes in Eclipse Collections, we can see that there are no anonymous LazyIterable types in the Eclipse Collections library. There are many more LazyIterable types in Eclipse Collections than there are in the JDK for Stream, so I can’t just take a screenshot, but I can copy all the types to the clipboard. Notice that none of the types say “Anonymous.”
AbstractLazyIterable (org.eclipse.collections.impl.lazy)
ChunkBooleanIterable (org.eclipse.collections.impl.lazy.primitive)
ChunkByteIterable (org.eclipse.collections.impl.lazy.primitive)
ChunkCharIterable (org.eclipse.collections.impl.lazy.primitive)
ChunkDoubleIterable (org.eclipse.collections.impl.lazy.primitive)
ChunkFloatIterable (org.eclipse.collections.impl.lazy.primitive)
ChunkIntIterable (org.eclipse.collections.impl.lazy.primitive)
ChunkIterable (org.eclipse.collections.impl.lazy)
ChunkLongIterable (org.eclipse.collections.impl.lazy.primitive)
ChunkShortIterable (org.eclipse.collections.impl.lazy.primitive)
CollectBooleanToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
CollectByteToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
CollectCharToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
CollectDoubleToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
CollectFloatToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
CollectIntToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
CollectIterable (org.eclipse.collections.impl.lazy)
CollectLongToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
CollectShortToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
CompositeIterable (org.eclipse.collections.impl.lazy)
DistinctIterable (org.eclipse.collections.impl.lazy)
DropIterable (org.eclipse.collections.impl.lazy)
DropWhileIterable (org.eclipse.collections.impl.lazy)
FlatCollectBooleanToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
FlatCollectByteToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
FlatCollectCharToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
FlatCollectDoubleToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
FlatCollectFloatToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
FlatCollectIntToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
FlatCollectIterable (org.eclipse.collections.impl.lazy)
FlatCollectLongToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
FlatCollectShortToObjectIterable (org.eclipse.collections.impl.lazy.primitive)
Interval (org.eclipse.collections.impl.list)
KeysView in ObjectBooleanHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectBooleanHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectByteHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectByteHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectCharHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectCharHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectDoubleHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectDoubleHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectFloatHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectFloatHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectIntHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectIntHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectLongHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectLongHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectShortHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeysView in ObjectShortHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ByteBooleanHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ByteByteHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ByteCharHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ByteDoubleHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ByteFloatHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ByteIntHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ByteLongHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ByteObjectHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ByteShortHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in CharBooleanHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in CharByteHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in CharCharHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in CharDoubleHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in CharFloatHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in CharIntHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in CharLongHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in CharObjectHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in CharShortHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in DoubleBooleanHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in DoubleByteHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in DoubleCharHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in DoubleDoubleHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in DoubleFloatHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in DoubleIntHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in DoubleLongHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in DoubleObjectHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in DoubleShortHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in FloatBooleanHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in FloatByteHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in FloatCharHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in FloatDoubleHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in FloatFloatHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in FloatIntHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in FloatLongHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in FloatObjectHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in FloatShortHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in IntBooleanHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in IntByteHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in IntCharHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in IntDoubleHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in IntFloatHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in IntIntHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in IntLongHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in IntObjectHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in IntShortHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in LongBooleanHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in LongByteHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in LongCharHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in LongDoubleHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in LongFloatHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in LongIntHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in LongLongHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in LongObjectHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in LongShortHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectBooleanHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectBooleanHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectByteHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectByteHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectCharHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectCharHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectDoubleHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectDoubleHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectFloatHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectFloatHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectIntHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectIntHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectLongHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectLongHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectShortHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ObjectShortHashMapWithHashingStrategy (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ShortBooleanHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ShortByteHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ShortCharHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ShortDoubleHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ShortFloatHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ShortIntHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ShortLongHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ShortObjectHashMap (org.eclipse.collections.impl.map.mutable.primitive)
KeyValuesView in ShortShortHashMap (org.eclipse.collections.impl.map.mutable.primitive)
LazyIterableAdapter (org.eclipse.collections.impl.lazy)
ListIterableParallelBatchLazyIterable in ListIterableParallelIterable (org.eclipse.collections.impl.lazy.parallel.list)
RejectIterable (org.eclipse.collections.impl.lazy)
ReverseIterable (org.eclipse.collections.impl.lazy)
SelectInstancesOfIterable (org.eclipse.collections.impl.lazy)
SelectIterable (org.eclipse.collections.impl.lazy)
SortedSetIterableParallelBatchLazyIterable in SortedSetIterableParallelIterable in ImmutableTreeSet (org.eclipse.collections.impl.set.sorted.immutable)
TakeIterable (org.eclipse.collections.impl.lazy)
TakeWhileIterable (org.eclipse.collections.impl.lazy)
TapIterable (org.eclipse.collections.impl.lazy)
UnifiedSetParallelSplitLazyIterable in UnifiedSetParallelUnsortedIterable in UnifiedSet (org.eclipse.collections.impl.set.mutable)
UnifiedSetParallelSplitLazyIterable in UnifiedSetParallelUnsortedIterable in UnifiedSetWithHashingStrategy (org.eclipse.collections.impl.set.strategy.mutable)
ZipIterable (org.eclipse.collections.impl.lazy)
ZipWithIndexIterable (org.eclipse.collections.impl.lazy)
Don’t forget the primitive Streams
There are three primitive Stream types that might have anonymous or named inner classes. Let’s take a look at IntStream.

IntStream subtypes
As we can see, most of the implementations are anonymous so will be more of the dollar variety of names followed by a number.
The equivalent in Eclipse Collections is LazyIntIterable. Let’s look at LazyIntIterable.

LazyIntIterable subtypes
Again, we see there are no anonymous subtypes of LazyIntIterable.
If we were to look at LongStream and DoubleStream, the story would be the same. Mostly anonymous types. If we look at all of the primitive LazyIterable types in Eclipse Collections, of which there are eight total, all the types would have names.
Final Thoughts
Naming things is hard, but it doesn’t mean we shouldn’t try. Not naming things can be very hard on developers reading your code and looking at your types on the Java heap. Lambdas are a bit of an exception because they bring great readability in your code, and at least tell you in the JOL and jmap output that you are looking at a lambda by having $$Lambda in the type name.
If you don’t use JOL or jmap, you might not see the anonymous names as a big deal. Unfortunately, these names show up in stack traces and debuggers as well. At least in the debugger you can step into specific code, but the name on the stack trace will not help you decide where to click to jump in.
I hope you found this helpful. Thanks for reading!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions. I am the author of the book, Eclipse Collections Categorically: Level up your programming game.
메타데이터
- post_id
- 7b9cbc39f65f
- slug
- what-if-java-consistently-used-intention-revealing-names-for-types-7b9cbc39f65f
- url
- https://medium.com/@donraab/what-if-java-consistently-used-intention-revealing-names-for-types-7b9cbc39f65f
- canonical_url
- https://medium.com/@donraab/what-if-java-consistently-used-intention-revealing-names-for-types-7b9cbc39f65f
- author_url
- https://medium.com/@donraab
- status
- ok
- fetched_at
- 2026-07-10 21:04:09