writing an initialized static hashtable elegantly [duplicate] - java

This question already has answers here:
Initializing Hashtables in Java?
(10 answers)
Closed 5 years ago.
Is there a way to write a static final Hashtable in java in key value pairs just like you can initialize a string array conveniently as :
String [] foo = {"A","AB"};
Basically what I mean is not having to write the words "put" for key:value pairs but instead may be something like:
Hashtable<String, String> foo = {"JJ":"222","KK":"222"}
which IMO looks more elegant.
(I know the initialization would need to be in a static block. I am leaving that out for now)

An anonymous inner class would give you double brace initialization, which is useful in some cases:
static final Map<String, String> map = new HashMap<String, String>() {{
put("foo", "bar");
put("x", "y");
}};
In any case, #michael667's answer is probably the best

You can use guava's ImmutableMap:
map = ImmutableMap.of(key1, value1, key2, value2);
These convenience methods exist for one to five elements. If you need more, you can use an ImmutableMap.Builder:
static final ImmutableMap<String, Integer> WORD_TO_INT =
new ImmutableMap.Builder<String, Integer>()
.put("one", 1)
.put("two", 2)
.put("three", 3)
.build();

No, Java doesn't have map literals, but it does have array literals.
static final Map<String, String> map;
static {
map = new HashMap<String, String>();
String[][] pairs = {
{"foo", "bar"},
{"x", "y"}
};
for (String[] pair : pairs) {
map.put(pair[0], pair[1]);
}
}
Of course this doesn't really add anything to the straightforward copy and paste put solution, and it doesn't work well if your key and value types aren't the same.

No, you're looking for something like C#'s collection initializers, which doesn't currently exist in Java.
You can use an anonymous class to save a little typing, but you still have to write put.

Related

Good design pattern choice for initializing a hashmap in Java

I have a non-static class in Java that has a static hashmap field. The hashmap should be initialized with some key-value pairs generated by code. The hashmap is not to be changed after that.
How should this be achieved? Should I just create a static init method and make sure to run this once before using the class, or are there better ways of doing it?
You can use a static initializer block in your class.
e.g.
private static Map<String, String> myMap;
static {
HashMap<String,String> map = new HashMap<String,String>();
map.put("foo","bar");
myMap = Collections.unmodifiableMap(map);
}
You can easily create immutable maps with Google Guava library:
private static Map<String, String> map = ImmutableMap.of(
"key1", "value1",
"key2", "value2");
If you want to use it for many values then builder() is provided.

Newbie generic parameter qu estion... <T>

Okay so can i achive this somehow:
String myString = "someString";
Class myClass = myString.getClass();
HashMap<mClass, Integer> = new HashMap<myClass, Integer>();
So i would like to create a new hashmap, with class type of the key of my variables like Integer or String...
This is not possible. I'll walk you through the possibilities.
You could create a helper method, using generics. This will work because of all generics are compiled into simple Objects.
public static <T> Map<T, Integer> createMap(Class<T> cl)
{
return new HashMap<T, Integer>();
}
Now, you could use it like this:
Map<String, Integer> map = createMap(String.class);
However, this will require you to know what T is at compile time. So this won't work:
String str = "Test";
Class cl = str.getClass();
Map<String, Integer> map = createMap(cl); // Doesn't compile.
So, to conclude, this helper method isn't worth anything, because you could simply write:
Map<String, Integer> map = new HashMap<String, Integer>();
Due to type erasure this would not work.
A possible (but more verbose way) is to create a factory method that returns a Map based on the passed argument, eg:
MapFactory.create(String.class);
EDIT: In answer to #millimoose comment about this being not different from direct instantiation (which is true):
You could try to implement your own Map or decorate or extend the HashMap implementation so that it retains type information.

Java creating instance of a map object

Really simple question hopefully. I want to do something like this:
Map<String, String> temp = { colName, data };
Where colName, data are string variables.
Thanks.
Map is an interface. Create an instance of one the classes that implements it:
Map<String, String> temp = new HashMap<String, String>();
temp.put(colName, data);
Or, in Java 7:
Map<String, String> temp = new HashMap<>();
temp.put(colName, data);
#JohnGirata is correct.
If you're REALLY upset, you could have a look here http://nileshbansal.blogspot.com.au/2009/04/initializing-java-maps-inline.html
It's not quite what you're asking, but is a neat trick/hack non the less.
The quick way of putting entries in a Map just created is the following (let me use a HashMap 'cause I like them):
Map<String,String> temp = new HashMap<String,String>(){{
put(colName, data);
}};
Note all those parenthesis with a closing semicolon!
While it's true that in Java7 you can generally use the diamond operator and write something like this Map<String,String> temp = new HashMap<String,String>();, this does not work when putting elements in the Map inline. In other words, the compiler with yell at you if you try the following (don't ask me why):
Map<String,String> temp = new HashMap<>(){{
put(colName, data);
}};

How to define Map contents on initialisation? [duplicate]

This question already has answers here:
How can I initialise a static Map?
(43 answers)
Closed 6 years ago.
I was just wondering if it is possible to define the contents of a Map Object on initialisation.
For example, an array can be created, as:
new String[] {“apples”, “bananas”, “pears”}
So, I was wondering if there is something similar we can do for maps.
You can, sort of, using this syntax trick:
Map<String,String> map = new HashMap<String,String>() {{
put("x", "y");
put("a", "b");
}};
Not very pleasant, though. This creates an anonymous subclass of HashMap, and populates it in the instance initializer.
If your Map is going to be immutable after creation and you don't mind adding a dependency, Guava offers some nice fluent syntax:
Map<K,V> aMap = ImmutableMap.<K,V>builder().put(key0, val0).put(key1,val1).build();
If you're feeling really exotic, Scala has syntax exactly like what you want and is interoperable with other Java code:
val aMap = Map("a"->0, "b"->1)
Note that the Scala compiler will infer the Map generic type is from String to Int, based on what you put in it, though you can explicitly specify it as well.
However, if this is just a one-off, I'd go with the initializer-based syntax. Both the Guava library and Scala language have a lot else to recommend them, but learning a whole new library/language might be overboard.
You can use initializer blocks:
class Foo {
//using static initializer block
static Map<String,String> m1 = new HashMap<String,String>();
static {
m1.put("x","y");
m1.put("a","b");
}
//using initializer block
Map<String,String> m2 = new HashMap<String,String>();
{
m2.put("x","y");
m2.put("a","b");
}
}
Something very hacky..can be improved, but this is just a direction:
Define a static helper to convert an object array to a map of this type:
public static<K,V> Map<K, V> fromArray(Object[] anObjArray){
int size = anObjArray.length;
Map<K, V> aMap = new HashMap<K, V>();
for (int i=0;i<=size/2;i=i+2){
K key = (K)anObjArray[i];
V value = (V)anObjArray[i+1];
aMap.put(key, value);
}
return aMap;
}
then you can create a map using this:
Map<Integer, String> aMap = MapUtils.<Integer, String>fromArray(new Object[]{1, "one", 2,"two"});
I would personally second Gauva builder suggestion from #Carl though :-)

Java generics parameters with base of the generic parameter

I am wondering if there's an elegant solution for doing this in Java (besides the obvious one - of declaring a different/explicit function. Here is the code:
private static HashMap<String, Integer> nameStringIndexMap
= new HashMap<String, Integer>();
private static HashMap<Buffer, Integer> nameBufferIndexMap
= new HashMap<Buffer, Integer>();
// and a function
private static String newName(Object object,
HashMap<Object, Integer> nameIndexMap){
....
}
The problem is that I cannot pass nameStringIndexMap or nameBufferIndexMap parameters to the function. I don't have an idea about a more elegant solution beside doing another function which explicitly wants a HashMap<String, Integer> or HashMap<Buffer, Integer> parameter.
My question is:
Can this be made in a more elegant solution/using generics or something similar?
Thank you,
Iulian
You could make your function generic too:
private static <E extends Object> String newName(E object,
HashMap<E, Integer> nameIndexMap){
....
}
This bounds the two parameters of the function together, so for a HashMap<String, Integer> you can only pass String instances as first parameter. This may or may not be what you exactly want: if you only want to get elements from the map, Jon's solution is simpler, but if you want to add this object to the map, this one is the only choice.
You want something like this:
private static String newName(Object object,
HashMap<? extends Object, Integer> nameIndexMap) {
....
}
or (as pointed out in the comments)
private static String newName(Object object,
HashMap<?, Integer> nameIndexMap) {
....
}
That will stop you from putting anything into the map, because you couldn't guarantee to get the key right - but you can get things out of the map and guarantee they'll be integers.
Note that this version doesn't make the method generic - which means it's simpler, but it doesn't provide the same type safety that Peter's version does, in that you can't guarantee that object is of the right type. Each approach has its pros and cons - use whatever is most appropriate based on the body of the method. (If you need to put an entry into the map, Peter's approach is definitely better.)

Categories