How to create an array of a collection? [duplicate]
The community reviewed whether to reopen this question 5 months ago and left it closed:
Original close reason(s) were not resolved
P开发者_JAVA百科ossible Duplicate:
What’s the reason I can’t create generic array types in Java?
HashSet<Integer>[] rows = new HashSet<Integer>[9];
gives me a compilation error: generic array creation.
The simple answer: do not mix arrays with generics!
Use a list of hashsets:
ArrayList<HashSet<Integer>> rows = new ArrayList<HashSet<Integer>>();
The problem here is that Java specification doesn't allow you to declare an array of generics object.
A workaround of it is to use the wildcard, but you will lose the type-safety:
HashSet<?>[] rows = new HashSet<?>[9];
for (int i = 0; i < rows.length; ++i)
rows[i] = new HashSet<Integer>();
This, in your case, won't create problems when you are going to check if an item is contained: you can easily do rows[0].contains(4)
but when adding new content you will be forced to cast the row to the right type and suppress the warning of unchecked cast itself:
((HashSet<Integer>)rows[0]).add(4);
A side note: if you feel pioneer just download the Trove Collections framework that has a not-generics, highly optimized version of an integer hashset made to work with primitive type, I'm talking about the TIntHashSet
class: it will solve your problem and you'll end up having faster code.
To quote Effective Java Second edition by Joshua Bloch, page 119
Because of these fundamental differences, arrays and generics do not mix well. For example, it is illegal to create an array of a generic type, a parameterized type, or a type parameter. None of these array creation expressions are legal:
new List<E>[], new List<String>[], new E[]
. All will result in generic array creation errors at compile time.Why is it illegal to create a generic array? Because it isn’t typesafe. If it were legal, casts generated by the compiler in an otherwise correct program could fail at runtime with a
ClassCastException
. This would violate the fundamental guarantee provided by the generic type system.
(I omitted the part that explains Generic type erasure)
The Generics chapter of this book is available as a PDF.
You can declare the generic on the type declaration, but not when you actually allocate the object. Not sure the exact reason, perhaps to re-enforce the concept that some generics information is not preserved at compile time.
Set<Integer> rows[] = new HashSet[3];
for (int i = 0; i < rows.length; i++) {
rows[i] = new HashSet<Integer>();
}
Any time you're chaining generics or nesting data structures like this, it's time to take a step back and think about what you're really trying to do.
Would this be better if it were encapsulated in a wrapper class? It will probably make things less complex later. A week from now when you have to debug something in your array of hashsets of arraylists of arrays of some simple datatype because you thought you'd just keep wrapping them, you'll be sorry.
-edit: arrays are illegal? Point noted. I still feel the argument here stands.
You're using Java; don't be afraid to make some extra classes.
public class MyIntegers {
private HashSet<Integer> theIntegers;
// wrap methods
public boolean add(Integer i) { return theIntegers.add(i); }
public boolean contains(Integer i)...
public boolean remove(Integer i)...
}
// later...
public static void main(String[] args) {
MyIntegers[] rows = new MyIntegers[NUM_ROWS];
}
精彩评论