Why can Java Collections not directly store Primitives types?

JavaCollectionsTypesPrimitive Types

Java Problem Overview


Java collections only store Objects, not primitive types; however we can store the wrapper classes.

Why this constraint?

Java Solutions


Solution 1 - Java

It was a Java design decision, and one that some consider a mistake. Containers want Objects and primitives don't derive from Object.

This is one place that .NET designers learned from the JVM and implemented value types and generics such that boxing is eliminated in many cases. In CLR, generic containers can store value types as part of the underlying container structure.

Java opted to add generic support 100% in the compiler without support from the JVM. The JVM being what it is, doesn't support a "non-object" object. Java generics allow you to pretend there is no wrapper, but you still pay the performance price of boxing. This is IMPORTANT for certain classes of programs.

Boxing is a technical compromise, and I feel it is implementation detail leaking into the language. Autoboxing is nice syntactic sugar, but is still a performance penalty. If anything, I'd like the compiler to warn me when it autoboxes. (For all I know, it may now, I wrote this answer in 2010).

A good explanation on SO about boxing: https://stackoverflow.com/questions/1040384/why-do-some-languages-need-boxing-and-unboxing

And criticism of Java generics: https://stackoverflow.com/questions/520527/why-do-some-claim-that-javas-implementation-of-generics-is-bad

In Java's defense, it is easy to look backwards and criticize. The JVM has withstood the test of time, and is a good design in many respects.

Solution 2 - Java

Makes the implementation easier. Since Java primitives are not considered Objects, you would need to create a separate collection class for each of these primitives (no template code to share).

You can do that, of course, just see GNU Trove, Apache Commons Primitives or HPPC.

Unless you have really large collections, the overhead for the wrappers does not matter enough for people to care (and when you do have really large primitive collections, you might want to spend the effort to look at using/building a specialized data structure for them).

Solution 3 - Java

It's a combination of two facts:

  • Java primitive types are not reference types (e.g. an int is not an Object)
  • Java does generics using type-erasure of reference types (e.g. a List<?> is really a List<Object> at run-time)

Since both of these are true, generic Java collections can not store primitive types directly. For convenience, autoboxing is introduced to allow primitive types to be automatically boxed as reference types. Make no mistake about it, though, the collections are still storing object references regardless.

Could this have been avoided? Perhaps.

  • If an int is an Object, then there's no need for box types at all.
  • If generics aren't done using type-erasure, then primitives could've been used for type parameters.

Solution 4 - Java

There is the concept of auto-boxing and auto-unboxing. If you attempt to store an int in a List<Integer> the Java compiler will automatically convert it to an Integer.

Solution 5 - Java

Its not really a constraint is it?

Consider if you wanted to create a collection that stored primitive values. How would you write a collection that can store either int, or float or char? Most likely you will end up with multiple collections, so you will need an intlist and a charlist etc.

Taking advantage of the object oriented nature of Java when you write a collection class it can store any object so you need only one collection class. This idea, polymorphism, is very powerful and greatly simplifies the design of libraries.

Solution 6 - Java

The main reason is the java design strategy. ++

  1. collections requires objects for manipulation and primitives are not derived from object so this can be the other reason.
  2. Java primitive data types are not reference type for ex. int is not an object.

To Overcome:-

we have concept of auto-boxing and auto-unboxing. so if you are trying to store primitive data types compiler will automatically convert that into object of that primitive data class.

Solution 7 - Java

I think we might see progress in this space in the JDK possibly in Java 10 based on this JEP - http://openjdk.java.net/jeps/218.

If you want to avoid boxing primitives in collections today, there are several third party alternatives. In addition to the previously mentioned third party options there is also Eclipse Collections, FastUtil and Koloboke.

A comparison of primitive maps was also published a while ago with the title: Large HashMap overview: JDK, FastUtil, Goldman Sachs, HPPC, Koloboke, Trove. The GS Collections (Goldman Sachs) library was migrated to the Eclipse Foundation and is now Eclipse Collections.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJavaUserView Question on Stackoverflow
Solution 1 - JavacodenheimView Answer on Stackoverflow
Solution 2 - JavaThiloView Answer on Stackoverflow
Solution 3 - JavapolygenelubricantsView Answer on Stackoverflow
Solution 4 - JavaJeremyView Answer on Stackoverflow
Solution 5 - JavaVincent RamdhanieView Answer on Stackoverflow
Solution 6 - Javauser5693566View Answer on Stackoverflow
Solution 7 - JavaDonald RaabView Answer on Stackoverflow