Arraylist.clear() deletes content of hashTable - java

I have the following code:
podmienky.put(key, podmienkyOblast);
podmienkyOblast.clear();
podmienky is HashTable<String, ArrayList<String>> and podmienkyOblast is ArrayList<String>. If I put podmienky.get("index").size() before podmienkyOblast.clear() it returns 6 as it should. However if I put podmienky.get("index").size() after podmienkyOblast.clear() it returns 0. I thought that if I put something to hashtable I actualy add content of it to it. But as I can see it is storing only reference to arrayList. Am I wrong? How should I make this work?
Thanks in forward

You put a reference to your ArrayList into the Hashtable. If you want to add values from your ArrayList to the table, you have to iterate over the elements in the list.
for(Object element : podmienkyOblast) {
// TODO generate a key for your value here
String key = "...";
podmienky.put(key, element);
}

Java deals with Object reference, if you need to copy the object, you need to consider cloning (a.k.a deep copy).
Also, Favour interfaces over implementations, so use List instead of ArrayList.

Related

Updating HashMap in java

Do I need to remove value and then add or can I directly add it in HashMap and it will efficiently updated ?
i.e.
HashMap<String, String> person = new HashMap<String, String>();
person.add("name", "John");
now which would be a better/efficient way to update above key value :
a)
person.remove("name");
person.add("name", "jamy");
b)
person.add("name", "jamy");
or are both just the same ?
This is a very small example. Considering a large HashMap containing other HashMaps, which would be better option and is there any even more efficient way to do so ?
You can put the new value. It will substitute the old one.
From javadoc:
If the map previously contained a mapping for the key, the old value is replaced.
Note that the method is put, not add. add is not a method of Hashmap
Edited: I added the reference link to the documentation as Naman Gala commented.
Use put method, as it will replace value for given key if key exist , otherwise it will create new entry
java.util.HashMap provides put method to add key and object pair in the map. You do not have to remove the object if you want to update the HashMap object. It will return the previous object if there is any object in the map with the same key. Otherwise, it will simply return null. You do not have to remove it every time. Just use
java.util.HashMap.put(key, object);

ArrayList constructor accepting Collection

I have a simple question.
Lets say we have a Map, for example a Map<String, Object>
I want a method that returns a list of all values inside the Map.
The approach i use is the following:
I create a List<Object> myList = new ArrayList<>();
Get an iterator from the value set of the Map.
For each element inside the iterator i put a reference in the myList list.
Return the list
...later for each element i use i wrap it inside a synchronized block because the list contains references.
Now i am woring about using an easier apporach. The one i mean is the following:
return new ArrayList(myMap.values());
As you see in this case i simply use the constructor of the List interface which accepts a Collection.
And finally my question is:
If i use the second approach do i still get references or it copies the value objects that are inside the map?
In both cases you will get "shallow" copy of collecion, so both arrays will keep references to the same objects.
return new ArrayList(myMap.values()) will return an ArrayList containing the references of the original values of the Map. No copies of the values instances are created.
Note that if your Map contains duplicate values (i.e. values that are equal to each other), your ArrayList will also contain duplicate values. If you want to eliminate the duplicates, you should create a Set of the values instead of a List.
In either case you'll get a copy of the reference (so called "shallow copy").
There is no deep-copying (creating a completely new object with meaningfully equivalent fields -- also deep-copied) involved.

How to put Objects from one map to another?

I have a Map like this :
Map<String,GridCell> cellsMap
I pass this into a method and the return from that method should contain a Map(say answerMap) which contains all the entries of cellsMap map plus an extra entry that contains a String as the key and a String as the value . Something like :
Map<String,Object> answerMap = new ConcurrentHashMap<String,Object>();
//answer should first contain all the map entries of cellsMap and then add an extra entry like the following
answer.put(getId(), getSelectionValue()); // getSelectionValue() returns a String that contains coordinates of the selected cells.
return answerMap;
Have you considered the Map.putAll() method ?
e.g.
answerMap.putAll(cellsMap);
I don't think this is a good object model, by the way. I think you're better off creating a new class that contains your original map (maybe a copy) and an additional field for your String/String pair.
Otherwise you're throwing objects of different types into the same map, and that's going to make life complicated when you later extract that info. Each time you extract via a key you're going to have to check the type of the object returned. Note that ConcurrentHashMaps don't maintain insertion order.
Use clone() method.
HashMap answerMap = (HashMap)cellsMap.clone();
Map interface has putall() method which add all values of another object in Map.

Nested Hashmap updates all the values for all the keys instead the one I want to change

I have a hashmap that contains 10 children hashmap, each of these child hashmap 5 keys mapping to a String array. When I want to update a value for a specific key from a children hashmap, all the keys get updated instead; not only that, but also all the children hashmap get updated as well. This code illustrate what I'm doing.
HashMap<String, HashMap<String, String[]>> parentMap = new HashMap<String, HashMap<String, String[]>>();
for(String x : someArray){ // Adds 10 children hashmaps to parentMap
parentMap.put(x,new HashMap<String, String[]>());
for(String y : someOtherArray){ // Creates 5 keys for each of the children hashmaps
parentMap.get(x).put(y,stringArray);
}
}
parentMap.get(someKey).put(someOtherKey,modifiedArray); // This updates the entry I want to update.
When I update with that last instruction, I want to update specifically that key, however everything gets updated instead, all the keys for all the children hashmaps are updated instead the one I want.
Hopefully it makes sense, I'm not sure if this is the correct approach for this but I've been looking online for any tips on doing something similar without any luck. I'm not good at all with Java, if I can achieve the same result with something simpler, it will be welcome, note that I can't use a List or something like that, since it uses int indexes, I need to reference to my objects using a string (like a dictionary on python).
That is because you initialize all maps to contain stringArray, i.e., the same array.
This is why changing one of them, will change all of them.
If you want each key in each inner map to point to different copies of the array, you need to do something like
...
parentMap.get(x).put(y, Arrays.copyOf(stringArray, stringArray.length));
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
...
(You could also use for instance clone or create new arrays manually each time you need a new copy.)
#aioobe explained the reason.
Here is the solution. You have to create copy of initial array every time you put it into your map:
String[] tmpArr = new String[stringArray.length];
arraycopy(stringArr, 0, tmpArr, 0, stringArray.length);
parentMap.get(x).put(y,stringArray);

After converting List to Set, enhanced for loop throws a ClassCastException

I have a problem after I convert List<MyCustomObject> to a HashSet<MyCustomObject>. When I try to iterate through each element using an enhanced for I get a ClassCastException stating that "java.util.HashMap cannot be cast to MyCustomObject".
Here is the code:
List<MyCustomObject> myList = remoteMethod.getList();//the list is obtained via a REST call so it does go through the serialize/deserialize process...
Set<MyCustomObject> mySet = new HashSet<MyCustomObject>(myList);
for(MyCustomObject object : mySet) <----this is where it goes boooom!!!
{
DB.add(object);
}
So before the enhanced for statement I extracted the first object in the list and used .getClass and it DID come up as HashMap. Is something happening during serialization/deserialization? Or is it in the conversion of the List to Set? What could be going wrong, and how would I fix it?
Whatever is putting the data into the List that remoteMethod.getList() returns is putting HashMaps into it instead of MyCustomObjects. You should change it to put MyCustomObjects into the List.
The contents of the list are not guaranteed to be MyCustomObject instances at runtime, and that's probably what's creating your confusion.

Categories

Resources