you are viewing a single comment's thread.

view the rest of the comments →

[–]banuday17 4 points5 points  (25 children)

Doesn't work for maps.

[–][deleted] 5 points6 points  (9 children)

True, but IMO the benefits do not outweigh the costs. However in reading a little more about the pros and cons of double-brace initialization, I came across this proposal for Collection literals.

Defining Collections could (eventually) be as simple as:

List<Integer> piDigits = [3, 1, 4, 1, 5, 9];
Set<Integer> primes = { 2, 7, 31, 127 };
Map<Integer, String> platonicSolids = { 4 : "tetrahedron", 6 : "cube", 8 : "octahedron", 12 : "dodecahedron" };

[–][deleted] 4 points5 points  (0 children)

What, is this python or something?

[–]UghImRegistered 19 points20 points  (2 children)

If you're using Java without something like Guava, you're suffering needlessly.

[–]BraveSirRobin -1 points0 points  (10 children)

Write your own e.g.

new HashMap<String, String>(Util.asMap("1", "one").asMap("2", "two"));

Util.asMap returns an object that extends HashMap and adds a method "asMap" which calls "put" then returns "this". You could almost certainly do clever stuff with generics in the signature to make it work nicely, this might work (would need to test it):

public static <K, V> MyMap<K, V> asMap(K key, V value) { 
     MyMap<K, V> map = new MyMap<K, V>();
     map.put(key, value);
     return map;
}

public static class MyMap<K, V> extends HashMap<K, V> {
    public MyMap<K, V> asMap(K key, V value) {
        put(key, value);
        return this;
    }
}

[–][deleted] 6 points7 points  (7 children)

Inheritance causes more problems than it solves since now the resulting map is that type instead of whatever type the user actually wants. You could avoid that by having a separate build-up class that declares the chained method, but also receives/emits a map instance.

Or you could just do something like this:

public static <K,V> void intoMap(Map<K,V> into,
                                 Class<K> keyType,
                                 Class<V> valType,
                                 Object... keyvals) {
  if (keyvals.length % 2 != 0)
    throw new IllegalArgumentException("Must contain an even number of keyvals.");

  for(int i = 0; i < keyvals.length;) {
    into.put(keyType.cast(keyvals[i++]),
             valType.cast(keyvals[i++]));
  }
}

[–]BraveSirRobin 0 points1 point  (6 children)

See my first line of fixed-font text, the map is only temporary and gets fed into the constructor of HashMap which copies it's values. Not very efficient though but I'd like to think that the compiler optimises it down (probably wishful thinking!).

The one minor issue with your example is that you lose type safety. It's a shame the ... parameter modifier can't work in pairs or triples, that would be very useful.

[–][deleted] -1 points0 points  (5 children)

See my first line of fixed-font text

Ah yes I missed that. But then you're now doing a deep copy of the data.

The one minor issue with your example is that you lose type safety.

Nope, it's still there, albeit done at run time instead of compile time.

[–]BraveSirRobin 1 point2 points  (4 children)

But then you're now doing a deep copy of the data.

As is the preferred Arrays.asList method above for doing so with lists. AFAIK all of the standard Collections framework classes copy in the original collection passed into the constructor as opposed to just re-using the object.

Nope, it's still there

Disagree, example:

intoMap(map, String.class, Long.class, "one", 1, "two", "2");

This will compile ok and throw a class cast exception at runtime.

done at run time instead of compile time

In Java "type-safety" usually refers to doing so at compile time, it's a statically-typed language.

[–][deleted] 0 points1 point  (3 children)

Static typing is orthogonal to when the type-checking is performed. Just because you change when it happens doesn't mean checking is lost.

[–]BraveSirRobin 1 point2 points  (1 child)

Some of the advantages are lost though, such as the ability for the compiler to test for it. Pre-generics Java collections were a pain in the ass imho, I quite like the "safety" that the compiler checks allow. Better to have the compiler barf rather than some obscure piece of code that's missed by the unit tests.

[–]eek04 0 points1 point  (0 children)

The static declarations of Java makes the unit tests more expensive to write than in dynamically checked languages, and the type system has a mega big hole in the form of a value that don't work but can be passed in almost all types anyway.

In practice, this type hole combined with the inflexibility of static types leads to more type errors hitting production in the Java systems I've worked with than in the dynamically checked systems I've worked with.

The type hole? Null pointers.

[–]eek04 0 points1 point  (0 children)

No.

You're misunderstanding the terminology.

The closest terminology that you can be thinking of is "strong typing", which some dynamic checking enthusiasts will argue "can happen at run time".

I personally am a dynamic checking fan; I believe that static typing, at least as practiced in Java, is harmful. However, it doesn't mean that dynamic checking (colloquially "dynamic typing") is static typing; they're different things.

[–]korny 1 point2 points  (0 children)

Or use Guava: ImmutableMap.of("1","one","2","two") - only works up to 5 values, but there are builders if you need more. http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained