In the following snippet, I want list to be a collection of maps. Instead of creating a new HashMap every time, I tried to clear and reuse the previous variable.
List<Map> list = new ArrayList<>();
Map<String,String> aMap = new HashMap<>();
aMap.put("fou","bar");
list.add(aMap);
aMap.clear();
aMap.put("big", "bang");
list.add(aMap);
System.out.println(list.toString());
I was surprised the value inside the list is affected by the "clear" operation on the variable aMap, the output is as following:
[{big=bang}, {big=bang}]
What's going on here ?
It's a tricky question :) Basically the list holds a reference to the object and not a copy of the object. So when you add aMap to the list you add a reference to that Map variable. Then you modify it (and by doing that you modify that reference that you hold in the list) and then you add the same variable to the list again. So now you have two references (or pointers if you prefer) of the same object. That's why you get such result.
Since you have already added aMap in the beginning to the list,aMap goes on getting added to the list instead rewrite the code as below:
List<Map> list = new ArrayList<>();
Map<String,String> aMap = new HashMap<>();
aMap.put("fou","bar");
list.add(aMap);
aMap.clear();
aMap.put("big", "bang");
// list.add(aMap);> --commented since u have already started adding map values to the array list.
System.out.println(list.toString());
Related
I am trying to iterate through a hashmap which contains 8 entries. However one of these entries is a hashset 'balloon' with 2 objects within it. I want to add this to an array list so i can then iterate through it in a for loop/
First part of the code below works, I loop through the hashmap and look for the key I require which is 'balloon'. I need help to add the hashset to an array list.
I am getting a casting error when using Collectors.list and stream
//This is the hashmap I am looping through to find the balloon key
Map<String, Object> types = System.getPartyItems();
for (Map.Entry<String, Object> entry : types.entrySet()) {
if (StringUtils.contains(entry.getKey().toString(), "balloon")) {
//This is where I need to add the balloon hashset to a list to access the entries and values from within.
List<PartyItem> myPartyList = new ArrayList<>();
myPartyList.add (hash set of balloon objects)
Do i need to assign the hash set to a variable before i can set it to the list? Anything I've tried I am getting a casting error eg "class java.util.stream.ReferencePipeline$Head cannot be cast to class java.util.ArrayList"
Any help appreciated.
Thanks
Test if a value is a Set and if it is, add all items to your list.
if (StringUtils.contains(entry.getKey().toString(), "balloon")
&& entry.getValue() instanceof Set) {
myPartyList.addAll((Set)entry.getValue());
}
You can iterate like this:
for(String key: Map.keySet()){
if(StringUtils.contains(key, "balloon")){
Iterator<String> it = hashMap.get("balloon").iterator();
while(it.hasNext()){
// your code here
}
}
}
Instead of iterating through entry just iterate through keys and when you find the balloon get the hashset to iterate through it.
for(String key: types.keySet()){
if(StringUtils.contains(key, "balloon")){
for(Object object: types.get(key)){
//do what you need with object
}
}
}
After your edit it should be like this
for(String key: types.keySet()){
if(StringUtils.contains(key, "balloon")){
ArrayList<Set<PartyItem>> myList = new ArrayList();
myList.add(types.get(key));
}
}
Usually you structure your hashmap as <key, value> and you access your values via their corresponding keys. But they have to match exactly.
In your case your hashmap would look like this:
Map<String, Object> partyItems = myPartyList.getPartyItems();
// or maybe even
Map<String, PartyItem> partyItems = myPartyList.getPartyItems();
And getting the value is as easy as:
Object partyItem = partyItems.get("baloon");
If you are not sure if your paryItems contain a value for your key baloon you can check that first:
if (partyItems.contains("baloon")) {
Object partyItem = partyItems.get("baloon");
}
If you are looking for a part of the key matching baloon:
List<PartyItem> myFilteredPartyItems = partyItems.entrySet().stream()
.filter(e -> e.getKey().contains("baloon"))
.collect(Collectors.toList()))
This is called stream oriented programming (take a look at the Java Stream API), and if your run at least Java 8 you can use those.
And what it does, is turn the entries of the List to a stream, then remove everything which does not contain baloon in the key, and turn the resulting stream, which was not removed back to a list.
Here you also find a very informative tutorial on how to use streams in Java.
Okay, so I'm fairly new to programming so apologies if this problem is really simple, I've created an ArrayList inside my Hash Map so that I can add more than one value into my hash map.
My code looks fine (to me) but theres an error on this line "mymap.add(module, new ArrayList>());" saying ( or [ expected.
Wasted way too much time trying to figure this out so thought I'd post here. Thanks in advance for any help. Also: yes I need to do it this way and no I can't use guava MultiMap.
public class hashArray {
HashMap<String, ArrayList<Integer>> mymap = new HashMap<String, ArrayList<Integer>>();
public hashArray() {}
public void addEntryHR( String module, Integer result ) {
mymap.add(module, new ArrayList<Integer>>());
There is a typo and a bug in your line:
// The typo is right here v
mymap.add(mod, new ArrayList<Integer>>());
Remove one of the > and change add to put:
mymap.put(mod, new ArrayList<Integer>());
The error you get, is about the typo. Fixing that typo will give you an error about add to be an unknown method.
You need to first get the list out from map object like below-
ArrayList<Integer> list = mymap.get(mod);
if (list==null){
//then create new ArrayList object and assign to list
list=new ArrayList<Integer>();
}
list.add(number); //adding new number to the list
mymap.put(mod,list); //storing in map
The problems
You create a new ArrayList in new ArrayList<Integer>>() (with contains a syntax error as well - a > too many), but never add number to it.
You are calling add on a HashMap, which doesn't have this method. For maps, it is called put.
Proposed solution
Please see the code below
Map<String, List<Integer>> myMap = new HashMap<>();
public void addEntryHR(String mod, Integer number) {
List<Integer> numbers = new ArrayList<>();
numbers.add(number);
myMap.put(mod, numbers);
}
Other remarks
Use interfaces
It is advised to use the interfaces of the collections rather than the implementations. This means Map<String, String> myMap instead of HashMap<String, String> myMap and List<Integer> instead of ArrayList<Integer>.
Why do this? Because this allows you to be flexible in the collections you use and reduce maintenance effort. Say you change your mind and want to use LinkedList instead of ArrayList, then you just have to change one new ArrayList<>() to new LinkedList<>() instead of all the ArrayList variables used throughout the code.
I have a simple observation with a Map with String keys of date format.
List<String> a =new ArrayList();
a.add("as");
a.add("df");
a.add("vf");
a.add("fg");
HashMap<String,List> map = new HashMap<>();
map.put("2017-08-07", a);
System.out.println(""+map);
a.clear();
a.add("er");
map.put("2017-08-08", a);
System.out.println(""+map);
And Result is
{2017-08-07=[as, df, vf, fg]}
{2017-08-08=[er], 2017-08-07=[er]}
when i am clearing list and assign new key to my map then my old value also replacing.
But i want result be like
{2017-08-07=[as, df, vf, fg]}
{2017-08-08=[er], 2017-08-07=[as, df, vf, fg]}
How to achieve this, Any help really appreciated .
Thanks
The call on map.put does not mean that it will create an entirely new value for the List. You put a reference to the current List a there and if you modify a it will also modify it inside the Map. To avoid that, create a new List.
Change this line
map.put("2017-08-07", a);
to
map.put("2017-08-07", new ArrayList<>(a));
Thats because you are modifying the same instance of list, hence the modifications will effect everywhere. Create a new list if you want to have separate results otherwise you lost all the data everywhere when you clear it.
map.put("2017-08-07", a);
System.out.println(""+map);
List<String> b = new ArrayList<>();
b.add("er");
map.put("2017-08-08", b);
System.out.println(""+map);
Put a new List to map, so a won't be linked.
map.put("2017-08-07", new List<String>(a));
I don't have idea how to search this:
Random generator = new Random();
Map<Integer, ArrayList> mapOfprevOp = new HashMap<>();
ArrayList<Integer> listPrev = new ArrayList<>();
listPrev = mapOfprevOp.get(operacja);
System.out.println(listPrev); // it will show []
int rnd = generator.nextInt(op_cnt) + 1;
listPrev.add(rnd);
System.out.println(mapOfprevOp.get(operacja)); // it will show value of listPrev
Why second System.out print me on the screen value of listPrev?
It shouldn't still print [] ?
listPrev = mapOfprevOp.get(operacja);
This line works different than i could expect?
This would suggest that at your first System.out.println invocation the list is empty.
If you look here https://docs.oracle.com/javase/7/docs/api/java/util/AbstractCollection.html#toString%28%29. We can see that the toString method for a list returns the elements between square brackets. Thus [] is an empty list.
At the second call you have added an element which is why you see it. You need to bare in mind that in Java we pass objects by reference meaning that your listPrev references the SAME LIST as the one contained in the map.
If you want to just get the value, then I would suggest you change
listPrev = mapOfprevOp.get(operacja);
to be
listPrev.addAll(mapOfprevOp.get(operacja));
This will add all of the elements from mapOfprevOp.get(operacja) to listPrev without subsequent operations affecting the map which seems to be what you want.
Also, Map<Integer, ArrayList> mapOfprevOp = new HashMap<>(); Generally it is better to use interface types in delcarations like you have with Map. So I would consider switching ArrayList to be List.
The object that you use its self can still be an ArrayList, like this:
Map mapOfprevOp = new HashMap<>();
List listPrev = new ArrayList<>();
This means that if you wanted to change it to be a LinkedList, you would only change it in one place rather than 3. Note that with the exception of Arrays.asList lists all lists can be resized.
I need to create a list with values of type - (long,String)
like -
ArrayList a = new ArrayList();
a.add(1L,branchName);
How can I do this because if I use list It will accept only int,String.
You should note that ArrayList's add(int,String) adds the String element in the given int index (if the index is valid). The int parameter is not part of the contents of the ArrayList.
Perhaps an ArrayList is not the correct choice for you. If you wish to map Long keys to String values, use Map<Long,String>.
Map<Long,String> a = new HashMap<> ();
a.put(1L,branchName);
You can define a custom class, e.g.
class IndexAndBranchName {
long index;
String branchName;
}
and then add instances of this to the ArrayList:
ArrayList<IndexAndBranchName> a = new ArrayList<>();
a.add(new IndexAndBranchName(index, branchName));
Whether you use this approach or something like Eran's depends upon what you need to use the list for subsequently:
If you want to look "branches" up by index, use a Map; however, you can only store a single value per key; you could use a Guava Multimap or similar if you want multiple values per key.
If you simply want all of the index/branch name pairs, you can use this approach.
You can use the below code for your question.
HashMap is also a better option , but if you want only ArrayList then use it.
List<Map<Object, Object>> mylist = new ArrayList<Map<Object, Object>>();
Map map = new HashMap<>();
map.put(1L, "BranchName");
mylist.add(map);