I have a system that involves loading 'PlayerValue' Objects. The objects are formatted as such: [Header] value. I have these saved in a text file and whenever I save or read from the file, I want to remove duplicate headers. So I did this:
first, I load all of the PlayerValues from the file into an ArrayList called 'array', then:
for (PlayerValue v : array) {
for (PlayerValue v1 : array) {
if (v1.header.equals(v.header)) {
array.remove(v1);
}
}
}
Here you can see, it goes through each item of the array, then for each item, it searches the array again for the same header.
This would effectively remove duplicate headers, except for the fact that it throws a ConcurrentModificationException.
Any help for a work around?
Even if this worked, it would be a bad way to remove duplicates. A better option would be to have a Map<Header, PlayerValue>:
Map<String, PlayerValue> map = new HashMap<>();
for (PlayerValue v : array)
map.put(v.header, v);
Now you can iterate through this map's entries, which will not contain duplicate keys (headers):
array.clear();
for (Entry<?, PlayerValue> e : map.entrySet())
array.add(e.getValue());
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.
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.
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), "");
}
}
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
}
}
}
Previously I set up an ArrayList to contain objects of records. I have since replaced the ArrayList with a HashMap where the objects are stored and use the username string of an individual as the key.
The class of this directory implemented Iterable through implements Iterable<Object> (just a one off question, but why is <Object> required?).
The previous code used to iterate over the ArrayList was:
public Iterator iterator() {
return records.iterator();
}
I then used this iterator for all objects in that class as follows:
for (Object o : directory) {
TelephoneRecords temp = (TelephoneRecords) o;
System.out.println(temp.toString());
}
Unfortunately, the HashMapName.iterable(); seems to raise issues, so how do I go about this behaviour with a HashMap?
If you're only interested in the keys, you can iterate through the keySet() of the map:
Map<String, Object> map = ...;
for (String key : map.keySet()) {
// ...
}
If you only need the values, use values():
for (Object value : map.values()) {
// ...
}
Finally, if you want both the key and value, use entrySet():
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// ...
}
Hope this helps you.
You can iterate over the entrySet of the HashMap. The entrySet contains the sets of keys and values. The keys and values are then accessible through getKey() and getValue(). This can be done by the following code:
for (Map.Entry<String, Object> entry : map.entrySet()) {
String username = entry.getKey();
TelephoneRecord record = (TelephoneRecord)entry.getValue();
// Do something with username and record ...
}
Your off-question:
Object is a type parameter for the HashMap, which says that the Iterable contains Objects. If your HashMap is only supposed to contain TelephoneRecords objects, replace
implements Iterable<Object>
with
implements Iterable<TelephoneRecords>
That way you're saying that your Iterable contains TelephoneRecords, which in turn lets you avoid casting and get compile errors instead of runtime errors if you're doing something wrong (which is prefered!). That would improve the above code to:
for (Map.Entry<String, TelephoneRecord> entry : map.entrySet()) {
String username = entry.getKey();
TelephoneRecord record = entry.getValue();
// Do something with username and record ...
}
What does "seems to raise issues" mean? In a HashMap, you can iterate over keys (map.keySet()), values (map.values()) or key-value pairs (map.entrySet()).
I solved my issue with replacing records.iterator(); (which didn't work) with records.values().iterator();. It seems you cannot iterate directly over a HashMap but you can iterate over the values (objects) within it.
Furthermore, the issue of getting and printing the contents of the HashMap, I solved through the following code. It iterates over the TelephoneRecords objects within the directory, as specified by TelephoneRecords o : directory and the Iterator method within the directory class. Then a temporary object is assigned to the TelephoneRecords object being iterated over, and the [custom] toString() method used to print out the string of that specific TelephoneRecords object.
for (TelephoneRecords o : directory) {
TelephoneRecords temp = (TelephoneRecords) o;
System.out.println(temp.toString());
}
And I ended up solving my little side question by following the help provided, using Iterator<TelephoneRecords> (rather than simply using Object) to iterate over the TelephoneRecords objects contained within the directory object.
You can use the entryset from the hashmap, then iterate over that in the same manner as you do already e.g.
for (Object o : Directory.getEntrySet()) {
}
Also, if you type your hashmap it will remove the need for the cast -
Map<String, TelephoneRecords>