Where better create Map in java? - java

Code:
public class MyClass {
private Map<Integer,String> myMap;
...........................
void methodFillMap(){
myMap=new HashMap<Integer, String>();
.....................
}
}
Or better like:
public class MyClass {
private Map<Integer,String> myMap=new HashMap<Integer, String>();
...........................
void methodFillMap(){
myMap.put(.....);
.....................
}
}
Are these 2 ways of creating map the same by efficiency and functionality?

No they are different functionally. In your first case every time the method methodFillMap is called a new map is created and you will lose information from the old Map whereas in your second case the object will persist with the information.

The "time penalty" for creating an object (the map) will probably be the same in both cases. The question is - do you want the instantiation to be faster or the cal to methodFillMap?

I believe the best way is the first one, that way you only create a new instance of the map when you really need it, so in case you never call the method "methodFillMap" you wont have an instance of an unused object in memory.

Related

Unable to Cast Map into Java Class

public class Model extends LinkedHashMap<String, Object>{
}
LinkedHashMap<String, Object> map = //instance of LinkedHashMap
Model model = (Model) map // Exception.
when I'm trying to cast LinkedHashMap<String,Object> into my Model class I'm getting class cast exception.
I'm basically using user defined method which expect Model as an argument that's why I'm casting my map into Model class
You cannot do that because Model is not an instanceof LinkedHashMap. Think in terms of memory allocation. What have you actually done? You have allocated enough memory for a LinkedHashMap but NOT for a Model. The compiler is trying to save you from yourself.
You cannot use LinkedHashMap where Model is expected, therefore you cannot cast.
Presumably Model has additional methods and more functionality than LinkedHashMap. Even if you did not add anything new in Model class yet, Java assumes that you will.
Possible solution: change
LinkedHashMap<String, Object> map = //instance of LinkedHashMap
to
LinkedHashMap<String, Object> map = //instance of Model
Another solution: change the code that uses Model class to use Map instead.
Still another approach: do not derive Model from Map, have Model own a Map. Change the code accordingly.
In general, you need to learn more about OO programming, especially the modern sort that deprecates inheritance in favor of aggregation.
API Specifications for the ClassCastException says:
Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance.
class P {
}
class C extends P {
}
P p = new P();
C c = (C) p;//java.lang.ClassCastException; Runtime Exception
If you really want to do it. You do it in this way:
LinkedHashMap map = new Model();
map.put("one", "1");
Model model = (Model) map; // Exception.
System.out.println(model);
referece: Explanation of "ClassCastException" in Java

More succinct way of creating a constant String map in Java

Good day all,
Considering the following code example:
import java.util.HashMap;
import java.util.Map;
public class StaticPractice {
private final Map<String, String> mapperMap;
public StaticPractice(){
mapperMap = new HashMap<String, String>();
mapperMap.put("Foo1", "Bar1");
mapperMap.put("Foo2", "Bar1");
mapperMap.put("Foo3", "Bar2");
mapperMap.put("Foo3", "Bar3");
//...
mapperMap.put("MoreFoo", "BarAgain");
}
public void doSomething(){
//use mapperMap
}
}
I am looking for a more succinct way of creating a Map data structure that has a whole lot of constant Strings mapping to a whole lot of other constant Strings. In use, the example is far from "clean" or elegant, and is very verbose (there are alot of predefined constant mappings).
The goal of the class is to map objects referenced by these predefined constant Strings. It is commonplace in my particular code convention to use private static final String for all String constant, this example as well breaks that convention.
Would greatly appreciate any input, the wealth of knowledge from SO contributors always humbles me.
Much thanks.
Edit: Requirement specifies no external files.
One approach would be to create a builder class that generates the map. This has the advantage that you can optimize for concise syntax. You can also do things like making the generated map immutable -- useful if you want to use it as a publically accessible constant.
In your example, I notice that you have more than one key mapping to the same value. So, it would be more concise to have a method that takes a value followed by a list of keys. You can also make it more concise by having the builder return itself so that you can "chain" method calls:
class Builder<K,V> {
final Map<K,V> map = new HashMap<K,V>();
Builder add(V value, K... keys) {
for(K key : keys) {
map.put(key, value);
}
return this;
}
Map<K,V> build() {
return Collections.unmodifiableMap(new HashMap<K,V>(map));
}
}
// Usage:
mapperMap = new Builder<String,String>()
.add("Bar1", "Foo1", "Foo2")
.add("Bar2", "Foo3")
...
.build();
Alternately you might take a look at the Guava ImmutableMap class, which has a builder using the chaining syntax, though it doesn't have a way to map multiple keys to a single value in one call.
I Think you can try using Properties instead of map or initializing the map by reading strings from a configration file.
The most succint way I know is to define your map as an anonymous subclass of HashMap with an instance initializer:
private final Map<String, String> mapperMap =
Collections.unmodifiableMap(new HashMap() {{ // instance initializer
put("Foo1", "Bar1");
put("Foo2", "Bar1");
put("Foo3", "Bar2");
put("Foo3", "Bar3");
}});
If you want it to be a final String, you can always create a class with a couple of constant strings and the use a list of objects of that class.
You can do it like this:
class MapClass {
private static final String key;
private static final String value;
}
List<MapClass> l = new ArrayList<>();

Cannot instantiate the type Set

I am trying to create a Set of Strings which is filled with the keys from a Hashtable so a for-each loop can iterate through the Set and put defaults in a Hashtable. I am still learning Java but the way I am trying to do it isn't valid syntax. Could someone please demonstrate the proper way of doing this and explain why my way doesn't work and theirs does.
private Hashtable<String, String> defaultConfig() {
Hashtable<String, String> tbl = new Hashtable<String, String>();
tbl.put("nginx-servers","/etc/nginx/servers");
tbl.put("fpm-servers","/etc/fpm/");
tbl.put("fpm-portavail","9001");
tbl.put("webalizer-script","/usr/local/bin/webalizer.sh");
tbl.put("sys-useradd","/sbin/useradd");
tbl.put("sys-nginx","/usr/sbin/nginx");
tbl.put("sys-fpmrc","/etc/rc.d/php_fpm");
tbl.put("www-sites","/var/www/sites/");
tbl.put("www-group","www");
return tbl;
}
//This sets missing configuration options to their defaults.
private void fixMissing(Hashtable<String, String> tbl) {
Hashtable<String, String> defaults = new Hashtable<String, String>(defaultConfig());
//The part in error is below...
Set<String> keys = new Set<String>(defaults.keySet());
for (String k : keys) {
if (!tbl.containsKey(k)) {
tbl.put(k, defaults.get(k));
}
}
}
Set is not a class, it is an interface.
So basically you can instantiate only class implementing Set (HashSet, LinkedHashSet orTreeSet)
For instance :
Set<String> mySet = new HashSet<String>();
Set is an interface. You cannot instantiate an interface, only classes which implement that interface.
The interface specifies behaviour, and that behaviour can be implemented in different ways by different types. If you think about it like that, it makes no sense to instantiate an interface because it's specifying what a thing must do, not how it does it.
HashMap's keySet() method already creates the set you need, so simply:
Set<String> keys = defaults.keySet();
This is a view of the keys in defaults, so its contents will change when changes are made to the underlying (defaults) map. Changes made to keys will be reflected in the map, as well, but you can only remove...not add...keys from the map.
If you need a copy of the keys that doesn't interact with the original map, then use one of the types suggested, as in:
Set<String> keys = new HashSet( defaults.keySet() );

HashMap<String, Object> : How to put Object itself as in place of String

A a = new A(); //classA { }
HashMap<String, Object> hm = new Hashmap<String,Object>();
hm.put("A", a);
My question is, How can i put the Object itself instead of "A" in same declaration?
hm.put(`a??`, a);
You simply cannot do that, the language prohibits it. It would only be possible if your class A is a subclass of String which is not possible, since String is declared as final in Java.
With respect to you interview question: It's not possible due to the generic type parameter that was chosen for the declaration. You can read more about that in Bounded Type Parameters.
A a = new A(); //classA { }
Map<A, A> hm = new Hashmap<A, A>();
hm.put(a, a);
But I do not see any point of putting a->a
If the class held a non-changing decent String field, you could use that.
// the id property must be a String, immutable and unique for each instance!
myMap.put(a.getId(), a);
If you want to make any object as a key in your HashMap, then that object has to be immutable.. Because, you don't want anyone to change your key, after you add them to your HashMap..
Just imagine, if your keys are changed after insertion, you won't ever be able to find your inserted value..
But if your key is immutable, then if anyone tries to change your keys, he will actually create a new one for himself, but you will still have yours..
That is what happens in case you use String as your key in HashMap(They can't be changed).. So, if you want your object to be a key, either you make your class a subclass of String (that you can't do), or, just make your class immutable..
This is actually possible using a raw type, like this:
Object key = ...;
Object value = ...;
Map<String, Integer> map = new HashMap<>();//a normal map
Map rawMap = map; // here is the raw type
rawMap.put(key, value); // it works!
This runs fine, but problems arise when you try to use the generic map later:
Integer value = map.get(key);// ClassCastException (unless value actually is an Integer)
That's why you were told that it's a "dirty trick". You shouldn't use it.

adding a key to HashMap without the value?

Is there a way to add a key to a HashMap without also adding a value? I know it seems strange, but I have a HashMap<String, ArrayList<Object>> amd I want to first be able to create keys as needed and then check if a certain key exists and, if so, put the appropriate value, namely the ArrayList<Object>
Was that confusing enough?
Since you're using a Map<String, List<Object>>, you're really looking for a multimap. I highly recommend using a third-party library such as Google Guava for this - see Guava's Multimaps.
Multimap<String, Object> myMultimap = ArrayListMultimap.create();
// fill it
myMultimap.put("hello", "hola");
myMultimap.put("hello", "buongiorno");
myMultimap.put("hello", "สวัสดี");
// retrieve
List<String> greetings = myMultimap.get("hello");
// ["hola", "buongiorno", "สวัสดี"]
Java 8 update: I'm no longer convinced that every Map<K, SomeCollection<V>> should be rewritten as a multimap. These days it's quite easy to get what you need without Guava, thanks to Map#computeIfAbsent().
Map<String, List<Object>> myMap = new HashMap<>();
// fill it
myMap.computeIfAbsent("hello", ignored -> new ArrayList<>())
.addAll(Arrays.asList("hola", "buongiorno", "สวัสดี");
// retrieve
List<String> greetings = myMap.get("hello");
// ["hola", "buongiorno", "สวัสดี"]
I'm not sure you want to do this. You can store null as a value for a key, but if you do how will be able to tell, when you do a .get("key") whether the key exists or if it does exist but with a null value? Anyway, see the docs.
You can put null values. It is allowed by HashMap
You can also use a Set initially, and check it for the key, and then fill the map.
Yes, it was confusing enough ;) I don't get why you want to store keys without values instead just putting empty arraylists instead of null.
Adding null may be a problem, because if you call
map.get("somekey");
and receive a null, then you do not know, if the key is not found or if it is present but maps to null...
//This program should answer your questions
import java.util.*;
public class attemptAddingtoHashMap { //Start of program
//MAIN METHOD #################################################
public static void main(String args[]) { //main begins
Map<String, ArrayList<Object>> hmTrial = new HashMap<String, ArrayList<Object>>();
ArrayList alTrial = new ArrayList();//No values now
if (hmTrial.containsKey("first")) {
hmTrial.put("first", alTrial); }
else {hmTrial.put("first",alTrial);}
//in either case, alTrial, an ArrayList was mapped to the string "first"
//if you choose to, you can also add objects to alTrial later
System.out.println("hmTrial is " + hmTrial); //empty now
alTrial.add("h");
alTrial.add("e");
alTrial.add("l");
alTrial.add("l");
alTrial.add("o");
System.out.println("hmTrial is " + hmTrial);//populated now
} //end of main
//#############################################################################################################
} //end of class
//Note - removing objects from alTrial will remove the from the hashmap
//You can copy, paste and run this code on https://ide.geeksforgeeks.org/

Categories