24

I've tried the following line:

Map<Character, Color> map={new Character('r'):Color.red,new Character('b'):Color.black};

But Netbeans 7 rejects this, with the error message '{' expected, ';' expected.

I've set the Source/Binary format as 'JDK 7'and the platform to 'JDK 1.7', is there anything else I need to do?

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
DaedalusUsedPerl
  • 772
  • 5
  • 9
  • 25

3 Answers3

52

Neither Java 7 nor Java 8 supports collection literals, as discussed in this question: Are Project Coin's collection enhancements going to be in JDK8?

You can use Google's Guava library if you need only immutable collections. ImmutableList, ImmutableSet and ImmutableMap have several overloaded factory methods or even builders that make creating collections easy:

List<Integer> list = ImmutableList.of(1, 1, 2, 3, 5, 8, 13, 21);
Set<String> set = ImmutableSet.of("foo", "bar", "baz", "batman");
Map<Integer, String> map = ImmutableMap.of(1, "one", 2, "two", 3, "three");

EDIT

Java 9 has added collection factory methods similar to those of Guava:

List.of(a, b, c);
Set.of(d, e, f, g);
Map.of(k1, v1, k2, v2)

Map.ofEntries(
    entry(k1, v1),
    entry(k2, v2),
    entry(k3, v3),
    // ...
    entry(kn, vn)
);
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
Natix
  • 14,017
  • 7
  • 54
  • 69
11

You need to define a concrete map implementation, optionally combined with double brace initialization:

Map<Character, Color> map = new HashMap<Character, Color>() {{ 
  put(new Character('r'), Color.red);
  put(new Character('b'), Color.black );
}};
Thomas
  • 87,414
  • 12
  • 119
  • 157
  • 2
    Hmm, if someone rates a post down, it would be nice to get some feedback why. We're all here to learn, aren't we? – Thomas May 23 '12 at 12:35
  • 8
    I personally didn't vote you down, but I see two problems with your code. First, creating an anonymous subclass just for initialization is not a very good practice. See http://stackoverflow.com/a/924536/581205 Second, you don't have to manually create a new Character instance, autoboxing does that for you: `put('r', Color.red);` – Natix May 23 '12 at 16:38
  • 8
    @Natix yes, the double brace initialization is not really recommended I just mentioned it as an answer to the OP's question. It's true that there are far better alternatives to achieve that. Besides that, creating a `Character` manually (manual boxing) or using autoboxing is not really a reason for a downrate. It's a matter of style and I tried to use as much of the OP's code as possible in order to keep confusion low. – Thomas May 24 '12 at 12:55
  • 2
    Should use valueOf on all the native classes, though. – stolsvik Sep 20 '14 at 22:45
  • I like this one. I have seen a similar construct elsewhere lately, but there people suggested to never ever use anonymous subclassing to write down literals. I disagree. – GhostCat Aug 22 '17 at 12:19
0

To expand a little on Thomas's answer... Map is an interface, and must be instantiated through one of the associated concrete implementations (HashMap, TreeMap, or LinkedHashMap). It is still good practice; however, to declare your reference variable as the interface implementation rather than the specific concrete, as it provides future flexibility.

Regarding the code snippet though, I think you do still need the Key-value pairs defined in the assignment side of the declaration. So, I would change:

Map<Character, Color> map = new HashMap<>() {{ 

to

Map<Character, Color> map = new HashMap<Character, Color>() {{ 
Seth
  • 322
  • 1
  • 7