Iterate through List<Object> given from Value within a Map - java

I am relatively unexperienced using such Java code. For getting forward in my Selenium automation I want to iterate through a Map>.
Right now I try to get near that iteration with the following code:
static Map<String, List<WebElement>> map = new Map<String, List<WebElement>>;
for (Map.Entry<String, List<WebElement>> entry : map.entrySet()) {
for (int i = 0; i < entry.getValue().size(); i++) {
*need to find code*
}
}
My intention is to iterate through all the WebElements within the Value of one Key within map
Will "entry.getValue().size()" get the Size of the List in that case? And how may I get a certain item out of the list in such a case? Any better solutions maybe?
Best regards

You can access both the key and the value from each map entry and do whatever you need. The key in this case is a string, and its value is a List<WebElement>. Once you have the list in hand, you can access its size and iterate over it.
for (Map.Entry<String, List<WebElement>> entry : map.entrySet()) {
String key = entry.getKey();
List<WebElement> list = entry.getValue();
// to iterate over the list, you can try
for (int i=0; i < list.size(); ++i) {
WebElement we = list.get(i);
// do something with this web element
}
}

My intention is to iterate through all the WebElements within the Value of one Key within map
That should be easy enough:
for( WebElement element : map.get(key) ) {
//do whatever is appropriate
}
There's one problem with the above: if get(key) returns null (either the key is not mapped or the map contain's the value null for that key) you get a NullPointerException. To fix that could first get the map, check if you didn't get null, then iterate:
List<WebElement> list = map.get(key);
if( list != null ) {
for( WebElement element : list ) {
//do whatever is appropriate
}
}
You might also want to have a look at Guava's ListMultimap, which always will return a collection/list on get() and makes handling maps with list values a lot easier.
Will "entry.getValue().size()" get the Size of the List in that case?
Yes since entry.getValue() should return a List unless you mapped null for the given key. And since you get a List the call to size() will return the list's size.
And how may I get a certain item out of the list in such a case?
If you know the index of that element just check whether the list actually contains that index, i.e. whether index >= 0 && index < list.size(). Then just get it with list.get(index).
If you don't know the index you need to iterate over the list and inspect each element until you reach the end or found the element you need. Alternatively, if you can sort the list by the property you're checking, you could also use binary search to locate the element, if it exists.
Note, though, that LinkedList has linear cost for get(index) and thus isn't well suited for getting by index or binary search, at least not if the list contains many elements.

Related

How can I iterate through a hashset within a hashmap?

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.

How to find next minimum in a hash map key?

I have a scenario where I have a map:
BiMap <Integer, String> map;
and a list which tracks the index which are processed.
List<Integer> filled;
While processing if the filled list contains the key then I should find the next min key from the map which is already not in the filled list.
Can some one tell me is there an easy way to do this without doing many iterations?
for (int i =0 ;i <size; i++) {
if(map.contiansKey(i)) {
Integer min = list.contains(i) ? getNextMinFrom(map, filled) : null;
if min != null ?System.out.println(map.get(min)) : continue;
}
}
For Eg:
Filled - 0, 4, 5, 6
Map - (1,dfs) (4,efs) (5,sdfs)
in the 0 th iteration.. output - dfs (1 is min)
in 4th iteration ... output shoudl be 4efs (4 is the next min)
....
The issue is I can not remove entries from the list.
use a TreeSet initialized with the 'KeySet' of your map and while you add Any key to filled remove it from 'TreeSet',as a result, the first element of TreeSet is what you want
Is this what you want to achieve? Start from the front of the filled array and go until you find the first value that is in filled but not in the map?
public int get smallestUnusedValue() {
for(int i = 0; i < filled.size(); i++)
if(!map.containsKey(filled.get(i)))
return i;
}
Do you need to use a HashMap specifically? Implementations of NavigableMap, such as TreeMap, provide methods to look up keys "adjacent to" a given value, without requiring an exact map. The higherEntry method seems to do what you want.

Remove entries from Java LinkedHashMap

I have to compare two Excel files (with different data) and create two new Excel tables:
Table 1 contains all matching entries
Table 2 contains all entries that not match
Therefore I iterate over both Excel files and store the matching entries in a LinkedHashMap. In a second LinkedHashMap I store all entries from the Excel file. With this two Maps I want to identify the delta.
To identify the delta I compare both lists and now want to remove all entries from the complete list, if the entry is already in the list with the matching ones.
I tried different solutions - all with the result that the code is running but never an entry is really removed. Can anyone help please?
Heres my code:
// This code fills both Maps
LinkedHashMap<String, String> liste_matches = new LinkedHashMap<String, String> ();
LinkedHashMap<String, String> liste_complete = new LinkedHashMap<String, String> ();
while(worksheet1.getLastRowNum() >= j){
liste_complete.put(String.valueOf(worksheet1.getRow(j).getCell(18)), "");
// Counter for loop, loops trough Telekom datasets
int i = 1;
while(worksheet2.getLastRowNum() >= i)
{
if(String.valueOf(worksheet1.getRow(j).getCell(18)).equals(String.valueOf(worksheet2.getRow(i).getCell(9))))
{
if(!liste_matches.containsKey(String.valueOf(worksheet1.getRow(j).getCell(18)))){
liste_matches.put(String.valueOf(worksheet1.getRow(j).getCell(18)), "");
}
}
}
// build Excel table
}
This is my code I used to compare both lists and remove all entries from liste_complete that are already in liste_matches.
I first tried this (I inserted the ArrayList for my second try...). It's running but without any effect to the list.
ArrayList list = new ArrayList();
for(Map.Entry<String,String> keyDelta : liste_complete.entrySet())
{
for(Map.Entry<String,String> key : liste_matches.entrySet()){
if(keyDelta.equals(key)){
liste_complete.remove(keyDelta);
list.add(entry.getValue());
}
}
}
Afterwards I tried this but also without any effect to the List:
for(int c = 0; c < list.size(); c++)
{
String str = list.get(c);
liste_complete.remove(str);
}
I found this solution in StackOverflow, but that returns java.lang.IllegalStateException
Iterator<Map.Entry<String,String>> iter = liste_complete.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String,String> entry = iter.next();
for(Map.Entry<String,String> key : liste_matches.entrySet()){
if(key.getValue().equalsIgnoreCase(entry.getValue())){
iter.remove();
}
}
}
AFAIK you can't remove element from a list you're iterating on.
I suggest you 2 solutions:
iterate on your lists to check for matching keys and store the match in the third list; then iterate on the third list and remove from liste_complete
refactor the first piece of code of your question so that you store in one list the matching values and in the other the non-matching. Pseudo code could be:
for worksheet1 row
for worksheet2 row
if(match)
liste_matches.add(...)
else
liste_non_matches.add(...)
In this way you do not have to remove elements afterwards.
Thanks a lot for your hints.
I already debugged the code but didn't understand the problem - I think it really was a problem of the complex input data.
I did not compare the keys via key.getKey() but only with key and that seems to cause problems in the comparison. Anyway, my code runs with this snippet:
for(Map.Entry<String,String> keyDelta : liste_Complete.entrySet()){
if(!liste.containsKey(keyDelta.getKey())){
delta_liste.put(String.valueOf(keyDelta), "");
}
}

Removing from a hashmap a specific value and the key

I want to remove a specific value from the hashmap and the key from that value. Look, for example if I have
hashMap.put(cold, frozen)
hashMap.put(cold,hard)
, in my graphic interface i will have cold=[frozen,hard].If I want to erase hard I want cold = [frozen] to stay
My hashMap is private HashMap<String,ArrayList<String>> hashMap ;
Here is what I tried but it's not good enough because if I have at 2 different key the value i want to remove, it only removes the value for the first and if I have for ex cold=[frozen,hard] and I erase hard it doesn't keep cold=[frozen];
for(String key : hashMap.keySet()){
int siz = hashMap.get(key).size();
for(int i = 0; i< siz;i++){
if(hashMap.get(key).get(i).equals(cuvant)){
s.remove(hashMap.get(key).get(i));
siz--;
hashMap.remove(key);
}
}
}
I forgot to mention that s is the arrayList with the values.
Are you putting an ArrayList with the values in a hashmap?
If so, then check for list size first:
if (! hashMap.get(key).isEmpty()){
hashMap.get(key).remove(ValueToRemoved)
}
add a condition
if (hashMap.get(key).isEmpty())
before
hashMap.remove(key);
This will ensure you delete a key only if the list associated with it is completely empty.
Also, make sure you do NOT keep iterating (the inner loop) after removing an element from the list if you use a for-each loop, it will get you a ConcurrentModificationException. If your list can have the same value multiple times (and should be removed multiple times), use the Iterator API rather than for-each loop.
Try this :-
HashMap<String, ArrayList<String>> m = new HashMap<>();
Iterator<Map.Entry<String,ArrayList<String>>> iter = m.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String,ArrayList<String>> entry = iter.next();
ArrayList<String> list = entry.getValue();
for(int i = 0 ; i < list.size() ; i++){
if(list.get(i).equals(cuvant)){
list.remove(i);
}
}
if(list.isEmpty())
iter.remove();
}

How to return keys of a map according to a condition?

I'm learning Java using BlueJ, I have made a class that has a HashMap of (Integer, String) that contains an ID number of somebody and their name.
I want a method to return a collection of all the keys that satisfy a condition, like if their ID number begins with 3 for example. I can't figure out how to do this.
And then another method that returns a collection of the values if they satisfy a condition, I was thinking it would be very similar to the previous method.
I know I need to loop through the map but I am not sure how to write the condition to populate the new map.
Here's an example that returns all the odd keys, in a Collection. Lists and Sets are Collections, in the same way that ArrayLists are Lists. You could change Collection to List (or even ArrayList) in this example and it would do the same thing.
public Collection<Integer> getOddKeys() {
// keySet is a method of Map that returns a Set containing all the keys (and no values).
Collection<Integer> result = new ArrayList<Integer>();
for(Integer key : map.keySet()) {
if((key % 2) == 0) // if the key is odd...
result.add(key); // ... then add it to the result
}
return result;
}
You should be able to modify this example to check the values instead - I won't just give you that code, because it's very similar, and easy to figure out if you understand how this example works.
You need to use the values method, which returns a collection of the values, in the same way that keySet returns a collection (more specifically, a set) of the keys. If you're wondering about why keySet returns a set and values doesn't, it's because you can use the same value twice in a map, but you can't use the same key twice.
You could do the following:
Create a holder list
Iterator over your map keys using map.keySet().iterator();
Check if the key start with 3, if yes add it to the key list.
return the keys list.
In your case (if the map is not too big), I'll get all keys of the map, then process them one by one to math my criteria:
Map<Integer, String> myMap=getFromSomeWhere();
for(Integer i : myMap.keySet() {
String k=String.valueOf(i);
if(k.startsWith("3")) {
//do what you want
}
}
public void CountryAbbriviationMap(String input)
{
map<string ,string> countrymap =new map<string ,string>{'Australia'=>'AUS','Argentina'=>'ARG', 'India'=>'IND'};
for(string key : countrymap.keySet())
{
if(key.startsWithIgnoreCase('A') && input.startsWithIgnoreCase('A'))
{
system.debug(key); //TO GET KEYS
system.debug(countrymap.get(key)); //TO GET VALUES
}
}
}

Categories