Ned
Ned

Reputation: 293

Map of Collections vs. Map of TreeSets - what is correct syntax?

I'm representing brands with their associated products like so:

In code this is represented by a TreeMap<String, TreeSet<String>>, as the brands will stay sorted alphabetically and enforce no duplicate brands or products. Created by this line:

private TreeMap<String, TreeSet<String>> products = loadProducts(RAW_PRODUCTS);

I'm still learning Java, but isn't one of the maxims of good OO to use the most-general type wherever you can? So I have this method that takes in this same Map and does some processing:

void initProductList(final Map<String, Collection<String>> products)

And you can see the TreeMap has become Map and the TreeSet has become Collection. But whenever I try to call:

initProductList(products);

The compiler error shows:

The method initProductList(Map<String,Collection<String>>) in the type AddAlertItem is not applicable for the arguments (TreeMap<String,TreeSet<String>>)

to make it easier to read, this is the difference it's confused on:

Map<String,Collection<String>>
TreeMap<String,TreeSet<String>>

The difference between TreeSet and Collection is tripping it up. But I'm not sure what to change to make it work. I could downcast the method parameters to specify the TreeSet directly, but then I feel I'd be limiting myself as I may want to use another type of Collection elsewhere.

Is there something I'm not thinking of, or a way to make this work without giving up the more-generic method parameters?

I've searched a bit on google and here and not found anyone dealing with this issue.

Upvotes: 1

Views: 82

Answers (4)

Makoto
Makoto

Reputation: 106460

Collection is pretty high up the Collections hierarchy. Why not strengthen the API reference a little bit and go with Set instead?

void initProductList(final Map<String, ? extends Set<String>> products) {

}

This way, it's explicitly clear that you're working with Set, and not List or some other collection type, as sets behave differently than lists do.

Oh, and it'll also compile.

Upvotes: 2

BatScream
BatScream

Reputation: 19700

Limit it to a Set and not a Collection and use it as below:

 void initProductList(final Map<String, ? extends Set<String>> products){}

Upvotes: 2

Grisha Weintraub
Grisha Weintraub

Reputation: 7986

You can pass any collection to your method as follows :

void initProductList(final Map<String, ? extends Collection<String>> products)

Upvotes: 2

Jiang
Jiang

Reputation: 588

I'm afraid @Makoto has got it wrong.

When compiling the codes, jvm will erase the generic type in <Type>. So it can't recognize the relationship of extends or implements between TreeSet and Collection. As long as the generic types are different, the compiler will show an error. However, ? extends Collection<String> will work.

Upvotes: 2

Related Questions