Java: create a list of HashMaps - java

I tried to create a list of maps. In the following code, I'm expecting to get
[{start=1,text=ye}, {start=2,text=no}]
however, I only got
[{start=2,text=no}, {start=2,text=no}]
How to avoid overriding the first map? Here is my code:
HashMap mMap = new HashMap();
ArrayList list = new ArrayList();
list.add(new HashMap());
mMap.put("start",1);
mMap.put("text","yes");
list.add(mMap);
mMap.put("start",2);
mMap.put("text","no");
list.add(mMap);
System.out.println("Final result: " + list );
thanks!
==========================
As a learner of Java who came from a procedure language background (SAS), I spent quite a few hours learning and experimenting ArrayList, LinkedList, Map, LinkedMap, etc--- I coldn't get it to work. And I don't understand why with my limited knowledge. Now, these following answers are all excellent! They explained very important data structure in Java, at least for me.
THANK YOU ALL!!!!

You need to create a new HashMap for every entry, instead of reusing the existing one. This would work:
HashMap mMap = new HashMap();
mMap.put("start",1);
mMap.put("text","yes");
list.add(mMap);
mMap = new HashMap(); // create a new one!
mMap.put("start",2);
mMap.put("text","no");
list.add(mMap);
also, you can remove the list.add(new HashMap()); as that adds an empty map to your list that is never populated.

Something which is maybe also worth mention it, is that you should define the type of the elements you use in the List, for the HashMap its not possible because you are mixing Integers and Strings.
And another thing is that you should use the List interface as type, so you are able to change the implementation (ArrayList or whatever) in the future.
Here the corrected code:
Map mMap = new HashMap();
List<Map> list = new ArrayList();

Yes, hash map from this piece of code
list.add(new HashMap());
is never referenced. So eventually you get a list of 3 items, 2 of which are identical however.

You are never saving a reference to this Map:
list.add(new HashMap());

have three adds to the list. the first add is to a new map instance; you never set any values. The second add you pass in a reference to nMap, which has 1, yes. The third add you pass the same reference. So the Map now has 3 references, the first to a map you never added any values to, the next 2 to the same map. which is why you get the same output.

When you put the same key name in the map then values will be overridden to same key.
suppose we have
mMap.put("start",1);
mMap.put("start",2);
mMap.put("start",3);
mMap.put("start",4);
it will not make map of length 4, as the key("start") is same so it will override the values on the same key. so you will get the get only one value (4) against "start" key.
To avoid this you will have to change the name of keys in a hashmap but in your scenaro, you need an other instance of hashmap to save the key and values as you are maintaining the arralist.

Related

Java HashMap - Optimized way of appending a new value to a vector which is a value in a HashMap<String, Vector<String>>

A similar way to appending new element to a vector like in C++ :-
myHashMap[myKey].push_back(newElement); //push newElement to the value vector directly
The only way i can think of in Java is to get the vector from hashmap. Append the new string to the vector and then set the key again with the new vector.
myValue = myHashMap.get(myKey);
/**Check if the key exists
**/
//If exists
myValue.add(newElement);
myHashmap.put(myKey, myValue);
Is the second approach as fast as the previous and if not is there any other approach? Thanks
You do not have to put back the vector back in the map as you are already modifying the vector when adding to it.
myHashMap[myKey].push_back(newElement);
is achieved by
myHashMap.get(myKey)
.add(newElement);
(assuming myHashMap.get(myKey) does not return a null).
You can use computeIfAbsent in the Map interface to construct a vector object for a key processed for the first time. This is more elegant and does not require a if block.
myHashMap.computeIfAbsent(key, k -> new Vector<>())
.add(newElement);
The function (k -> new Vector<>()) is only executed if the myHashMap does not have a mapping for the key key. The nice thing about this is it returns the vector value of key so that we can chain the add call on it.
Firstly, if you care about performance in Java, use ArrayList instead of Vector. As the javadoc says:
As of the Java 2 platform v1.2, [Vector] was retrofitted to implement the List interface, making it a member of the Java Collections Framework. Unlike the new collection implementations, Vector is synchronized. If a thread-safe implementation is not needed, it is recommended to use ArrayList in place of Vector.
So, assuming we are using Java 8 (and ArrayList), there are two translations for the C++ code.
Version #1. Works for Java 5+
HashMap<String, ArrayList<String>> myMap = new HashMap<>();
...
ArrayList<String> list = myMap.get(myKey);
if (list == null) {
list = new ArrayList<>();
myMap.put(myKey, list);
}
list.add(newElement);
Version #2. Works for Java 8+
HashMap<String, ArrayList<String>> myMap = new HashMap<>();
...
myMap.computeIfAbsent(key, k -> ArrayList<>()).add(newElement);
Which will be faster? You would need to test it to be sure, but I think that the second version should be a bit faster because it avoids the second hashmap lookup in the put call.
And 1 line of code is neater than 6 lines. (YMMV for readability. It depends on the person reading the code, and how familiar they are with Java 8+ language features and APIs.)
You can do this in the same way in java.
myHashMap.get(key).add(newValue)
Because in the hashmap the reference of list (or you can say it vector) is stored as value. So modifying the content of List will not influence the reference. You can imagine this reference likes 64bits address of a vector in c++.

Java: Setting key of a hashmap explicitly and keeping reference to it

public static HashMap<ArrayList<Integer>, String> map = new HashMap<ArrayList<Integer>, String>();
public static ArrayList<ArrayList<Integer>> keys = new ArrayList<>(map.keySet());
Then in main
map.put(key, "c");
(assume key is a valid ArrayList). But keys still has size 0 after that.
How can I make the relationship of keys stronger so that it will be actually tied to the HashMap and contain all its keys.
The copy constructor of ArrayList copies all the keys in the map to the ArrayList but if you change the map after that point it will not be reflected.
I can think of 3 options:
write your own map implementation that embeds an ArrayList and keeps it up to date
update the ArrayList manually everytime you update the map
don't use an ArrayList at all (keySet() is there when you need to access the keys so I'm not sure why you would need one)
You can't.
Map.keySet() returns the Map's current key set, which you then load into your list. Changes to the map after that have no effect on the contents of the list.
Most people would just re-get the key set if needed. Why don't you just do that?

How to get objects' index in a Java List

I'm trying to add data into array list. in this result
[{Store={id_store=2, namestore=Kupat Tahu Singaparna , product=[{id_product=1, price=100000, quantity=1}]}}]
you could use this code:
static ArrayList Storecart = new ArrayList();
LinkedHashMap store = new LinkedHashMap();
LinkedHashMap storeitem = new LinkedHashMap();
LinkedHashMap listproduct = new LinkedHashMap();
ArrayList prdct = new ArrayList();
storeitem.put("id_store",id_store);
storeitem.put("namestore",namestr );
listproduct.put("id_product", id_prodt);
listproduct.put("price",priced);
listproduct.put("quantity", quantity);
prdct.add(listproduct);
storeitem.put("product", prdct);
store.put("Store", storeitem);
Storecart.add(store);
I need to get the index of an object in the array list. The problem is, I can't looping array list for "get object Store, and object product" and find every index.. what will be the best & efficient solution ?
Well, you could use List.indexOf(), as others have suggested:
Java List API: indexOf()
If you plan on doing this a lot, then presumably you have a handle on your Object reference. So, you could just extend/wrap the Object you want the index of to keep track of its own index. Specifically, you could assign the Object its index based on the order you first encounter it or something. The order of the Object in the Collection would then be irrelevant.
I suppose you could also use a Map as yet another possibility. Then only work with the Map instead of an ArrayList.
Bottom-line: if you're doing a lot of "indexOf()" requests, then the ArrayList may not be the best container for your data.

Get ArrayList element by custom text indexing

What I'm doing is storing classes into an ArrayList and retrieve them by its index number. But are there any list classes in Java where I can retrieve a list element by, lets say, its name? Like this:
ArrayList<string> myArr = new ArrayList<string>();
myArr.add( "ID_name", "String to store" );
ands then retrieve it by:
myArr.get( "ID_name" );
Also, are there any other alternatives to ArrayList? I need a list class to be optimized for:
Random access
Only need to push items into the list
Never need to delete anything from the list
If all you want to store is key-value pairs, and don't care about iteration order, I think you might like the HashMap class:
Map<String, String> map = new HashMap<String, String>();
map.put("foo", "bar");
String bar = map.get("foo"); // bar is "bar"
You can use LinkedHashMap, so it will preserve the order, but you can extract elements by key as in regular map. Though you won't be able to extract entries by index.
An ArrayList is just that: an array. If you want to access values by something else than their indices, look for the various implementations of the Map interface (such as HashMap).
Use a Map<String, String>. In such structure, an element is added with a key. So you can get the element through the key:
Map<String, String> map = new HashMap<String, String>();
map.put("id", "string");
String s = map.get("id"); // s will be equals to "string".
As the other people have mentioned, a HashMap is probably what you want if you don't care about iteration order.
If you do, you can use a LinkedHashMap, which is really a HashMap bolted onto an LinkedList, giving you the best of both worlds: fast random access and preservation of iteration order.
Use a hashmap. You can add elements to a hashmap in much the same way as an arraylist. Also, you can create a set of keys ( 1 elements in the set per (key, value) pair)). You can then iterate over the set of keys.

Java - remove last known item from HASHMAP on MAP!s

OK so this is a BIT different. I have a new HashMap
private Map<String, Player> players = new HashMap<String, Player>();
How do I remove last known item from that? Maybe somethign like this?
hey = Player.get(players.size() - 1);
Player.remove(hey);
The problem is, a HashMap is not sorted like a list. The internal order depends on the hashCode() value of the key (e.g. String). You can use a LinkedHashMap which preserves the insert order. To remove the last entry on this you can use an iterator in combination with a counter which compares to the size and remove the last entry.
It's so easy. Try this:
Map<String, Player> players = new LinkedHashMap<String, Players>();
List<String> list = new ArrayList<String>(players.keySet());
map.remove(list.get(list.size()-1));
I'm a little bit confused. First of all, you're saying that you've got a new ArrayList and you're illustrating this with a line that creates a new HashMap. Secondly, does the Player class really have static methods like get(int) and remove(Object)?
HashMap doesn't have a particular order, ArrayList (as any other List) does.
Removing from an ArrayList
If you've got a list of players, then you can do the following:
private List<Player> players = new ArrayList<Player>();
// Populate the list of players
players.remove(players.size() - 1);
Here, I've used the remove(int) method of List, which allows to remove an item at an arbitrary index.
Removing from a HashMap
If you've got a map of players, there's no such thing as "the last item". Sure, you can iterate over the map and one of the items will pop out last, but that doesn't mean anything. Therefore, first you have to find out what you want to remove. Then you can do the following:
private Map<String, Player> players = new HashMap<String, Player>();
// Populate the map of players
// Find the key of the player to remove
players.remove(toRemove);
Here, I've used the remove(Object) method of Map. Note that in order to remove some key-value pair, you have to show the key, not the value.
There's no "first" and "last" in a HashMap. It's unordered. Everything is accessible by its key, not by index.
You cannot delete from HashMap like that. You need to use LinkedHashMap.
Simple, just do something of this effect.
1) Get a keyset iterator;
2) Create a Key somelastKey = null
3) Iterate through the iterator and assigning somelastKey until iterator finishes.
4) finally, do players.remove(somelastKey);
Bear in mind that HashMap is unordered, it depends on Object's hashCode to determine insertion order.
Instead of using HashMap, try using LinkedHashMap which keeps a predictable iteration order.
Hope this helps....
You'll probably have to extend HashMap, override put so that it caches the key, and then create a new method that just removes the key that was cached.
Unfortunately, this will only let you remove the most recently added. If you need to remove the most recently added multiple times (without inserting in-between the removes), you're out of luck.
In that case, I'd probably do the same overrides, just write the keys to a List. So you'd have both a list and a Map.
When adding:
String key; Player value;
lastKey = key;
map.put(key, value);
//...later...
Player lastAdded = map.remove(lastKey);
Other than that there's really no way without using a LinkedHashMap or in some way creating your own wrapper map or extending HashMap.
You shouldn't be using a raw hashmap anywhere because things like this happen.
Get in the habit of wrapping your collections in business logic classes.
See, in your case right now you need to associate these two related variables--your hashmap and a "Last entered" item so you can remove it.
If you need to remove the last item from some other class, you need to pass both items.
Any time you find yourself passing 2 or more items together into more than one API, you are probably missing a class.
Create a new class that contains the hashmap and a "lastAdded" variable. Have put and remove methods that are just forwarded to the hashmap, but the put method would also set the lastAdded variable.
Also be sure to add a removeLast() method.
NEVER allow access to your hashmap outside this class, it needs to be completely private (this is what I mean by wrapped). In this way you can ensure it doesn't get out of sync with the lastAdded variable (also completely private).
Just to reiterate getters and setters for these variables would be a terrible idea (as they are with nearly all actual OO code).
You will quickly find a bunch of other methods that NEED to be in this class in order to access data inside your hashmap--methods that never felt right in their current location. You will probably also notice that those methods always have an additional parameter or two passed in--those parameters should probably be members of your new class.
Once you get in the habit of doing actual OO design (via refactoring in this case), you'll find your code MUCH more manageable. To illustrate this point, if you find later that you need multiple levels of "delete last", it will be TRIVIAL to add to your class because it will be extremely clear exactly what methods can modify your hashtable and where your new "stack" of lastItems should be located--in fact it's probably a 2 line code change.
If you do not make this wrapper class, various locations will each have code to set "lastAdded" when they add code to the hashtable. Each of those locations will have to be modified, some may be in other classes requiring you to pass your new stack around with the hashtable. It will be easier to get them out of synch if you forget to change one location.

Categories