0

I'm currently looking for a way in java to do something like c#. For example in ASP MVC you can write:

DoMethod(new {key = value, another = value2});

Is there any nice way to do this in java? I've tried just an array: new object[] {value, value...} However that way i don't get the keys just the values.

I know you can do:

HashMap<String, object> map = new HashMap();
map.put("key", "value");
map.put("anoter", "value2");
DoMethod(map);

Unfortunately is that a cumbersome way if you need to do it a lot.

Cheers!

Caresi
  • 59
  • 2
  • 11

5 Answers5

2

No reinventing the wheel. If you're free to use 3rd-party libs, you can try Google Guava that offers strongly typed approach without static initializers and sub-classes, surrogate Entry/Pair-like classes or variadic arguments that may appear not type-safe:

Using the builder pattern:

final Map<String, Object> map = new ImmutableMap.Builder<String, Object>()
       .put("key", "value")
       .put("anoter", "value2")
       .build();
DoMethod(map);

Or even a shorter approach if the number of entries is up to 5 (see the overloads why all of those map factory methods are type-safe):

final Map<String, Object> map = ImmutableMap.<String, Object>of("key", "value", "anoter" "value2");
DoMethod(map);
Lyubomyr Shaydariv
  • 20,327
  • 12
  • 64
  • 105
  • I upvoted as this probably is best way to initialize a map. I gave more complex answer as I believe OP was asking more generally about how to pass "anonymous types" as parameters. The answer is that you can't do it but you can write simple classes and pass those instead. – Paul Boddington Dec 14 '14 at 23:51
0

There is nothing like that in Java itself. You would probably be able to find such features in other JVM languages, though. If you have the freedom of choice and you like dynamic typing and related features while retaining Java-like syntax, check Groovy out.

kaqqao
  • 12,984
  • 10
  • 64
  • 118
  • My Server is written in Java but thank you anyway :) – Caresi Dec 14 '14 at 16:34
  • Oh yeah, all JVM languages are compiled to the same bytecode, so you don't lose compatibility. In runtime, you have no clue what language the class was written in, nor do you care. And Groovy in specific is practically Java with more features, as almost all valid Java code is valid Groovy code. Java is an enterprise language, and as such its core evolves slowly by design. Speedy innovation is left to other JVM languages. – kaqqao Dec 14 '14 at 16:38
0

You can't do this sort of thing directly in Java but you can simulate it using varargs and a Pair class. First create a Pair class as follows.

public class Pair<T, U> {

    public static <T, U> Pair<T, U> of(T t, U u) {
        return new Pair<T, U>(t, u);
    }

    private final T t;
    private final U u;

    private Pair(T t, U u) {
        this.t = t; this.u = u;
    }

    public T first() { return t; }

    public U second() { return u; }
}

Then you can write methods using varargs:

static <K, V> Map<K, V> initialiseMap(Pair<K, V>... entries) {
    Map<K, V> temp = new HashMap<K, V>();
    for (Pair<K, V> pair : entries) {
        temp.put(pair.first(), pair.second());
    }
    return temp;
}

You can then initialise a Map by writing, for example

Map<String, Integer> map = initialiseMap(Pair.of("Key1", 1), Pair.of("Key2", 2));
Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
0

A simple solution is to use pair of arguments.

public static <K, V> Map<K, V> newMap(K key, V value, Object... keysAndValues) {
    Map<K, V> temp = new LinkedHashMap<K, V>();
    temp.put(key, value);
    for (int i = 0; i < keysAndValues.length; i+=2)
        temp.put((K) keysAndValues[i], (V) keysAndValues[i+1]);
    return temp;
}

Map<String, Integer> map = newMap("Key1", 1, "Key2", 2);
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • That's ok. Out of interest. What do you think of this kind of thing (either your solution or mine)? Do you recommend it? Or should we just wait until the language has proper map literals? – Paul Boddington Dec 14 '14 at 17:09
  • @pbabcdefp You could wait, but you might be waiting a while before these features are mainstream in Java. – Peter Lawrey Dec 14 '14 at 17:10
0

try:

doMethod(new HashMap(){{ put("key", "value"); put("another", "value2"); }});

Explenation:

  • Outer {} block means that this instance is of an anonymous class extends HashMap.
  • Inner {} block means a code that is copied to the anonymous class's constructor.
  • Elist
    • 5,313
    • 3
    • 35
    • 73
    • Double-brace initialization pattern, I think, should be finally considered harmful: another class is generated; it works for non-`final` classes only; it may cause (de)serialization issues. Also, nothing is "copied" to the anonymous class constructor in your case: the constructor is actually almost empty (just `super`-constructor delegation). The inner braces actually just embrace the class initializer that's invoked prior to the constructor call. – Lyubomyr Shaydariv Dec 14 '14 at 19:16
    • 1
      From http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html: "The Java compiler copies initializer blocks into every constructor". I agree it isn't an efficient approach (I don't know about the .NET version' sefficiency), but it is a language feature and in my opinion closer to what the OP asked for (syntex-wise) then any other answer here. – Elist Dec 14 '14 at 19:35
    • Another great finding for me these days. I just **always** believed that class initializers are JVM first-class citizens just like constructors are. The same thing for `finally`-ies -- as far as I know, they are copied too (that's why initializers cannot be accessed via reflection). I'm confused with _"The Java compiler copies initializer blocks into every constructor"_ (I'm not sure about the invocation graph then). Now I'm aware of that, thanks! :) – Lyubomyr Shaydariv Dec 14 '14 at 19:42
    • 1
      _I don't know about the .NET version_ -- In C# it's just syntax sugar. See http://stackoverflow.com/questions/459652/why-do-c-sharp-collection-initializers-work-this-way -- it's just chained `Add` method invocation. – Lyubomyr Shaydariv Dec 14 '14 at 19:48