5

This works ok:

Map aMap;
aMap = new HashMap<String, TreeSet<String>>();

This does not compile:

Map<String, Set<String>> aMap;
aMap = new HashMap<String, TreeSet<String>>();

Error message:

Compilation failed (26/05/2014 11:45:43) Error: line 2 - incompatible types - 
  found java.util.HashMap<java.lang.String,java.util.TreeSet<java.lang.String>>
  but expected java.util.Map<java.lang.String,java.util.Set<java.lang.String>>

Why?

Sameer Kazi
  • 17,129
  • 2
  • 34
  • 46
whytheq
  • 34,466
  • 65
  • 172
  • 267
  • What's the error message? – DBedrenko May 26 '14 at 10:43
  • 1
    Since in the first example `aMap` is defined without using generics, it does not perform the generic type validation (but it shows a warning!). The second example defines the types of `aMap`, so a proper check of types can be done (google for wildcards in generics). – SJuan76 May 26 '14 at 10:45
  • What's issue to this ? – Macrosoft-Dev May 26 '14 at 10:45
  • Basically for the first code the compiler tells you "I hope you are sure your code works properly, because I cannot tell"... in the second one, the compiler is sure that your definition is wrong. – SJuan76 May 26 '14 at 10:46
  • 1
    @Macrosoft-Dev the issue is my understanding – whytheq May 26 '14 at 10:47

3 Answers3

10

The first one works because you use a raw type (without generic) so you can put any type of map in there.

The second one doesn't work because a XXX<Set> is not a XXX<TreeSet>.

So you need to choose between:

Map<String, Set<String>> aMap = new HashMap<String, Set<String>>();
//or
Map<String, TreeSet<String>> aMap = new HashMap<String, TreeSet<String>>();

And in both case you will be able to write:

aMap.put("abc", new TreeSet<>());

The main difference is when you get an item from the map, with the former construct you won't have access to the TreeSet specific methods.

Finally, with Java 7+ you can omit the generic information on the right hand side and the compiler will determine it automatically for you:

Map<String, Set<String>> aMap = new HashMap<>();
Map<String, TreeSet<String>> aMap = new HashMap<>();
Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
  • +1 yes - I'm using 7+ so might be safer to just use the diamond notation ... seems strange to pick a non-specific notation to make things safer. – whytheq May 26 '14 at 10:56
3

Use this instead:

    Map<String, ? extends Set<String>> aMap;
    aMap = new HashMap<String, TreeSet<String>>();

Because the Set's generic must not be the same than TreeSet's generic.

Grim
  • 1,938
  • 10
  • 56
  • 123
  • 1
    Worth noticing that you won't be able to put any key-value pair in the map (except a key mapped to null). – Alexis C. May 26 '14 at 11:01
  • Using a more intelligent compiler this might work, you can write a FR if you like. – Grim May 26 '14 at 11:05
3

enter image description here

+1 to Peter's answer, TreeSet implements SortedSet which extends Set.

Map<String, ? extends Set<String>> aMap;
    aMap = new HashMap<String, TreeSet<String>>();

will work fine.

underdog
  • 4,447
  • 9
  • 44
  • 89