How to iterate list inside a map in ftl? - java

I have two value objects and i have to write a file using free marker while i am writing it using simply java i am able to iterate the list but don't know how to iterate a map whick consist a variable as well as a list. in my one value object BranchArea i have variable like name and id and a list of Branch. Branch is another value object who as a variable like name etc. i am iterating in java like this
List <BranchArea> branchAreaList = new ArrayList<BranchArea>();
Iterator<BranchArea> itrBranchArea = branchAreaList.iterator();
while (itrBranchArea.hasNext()) {
BranchArea branchAreaObj = itrBranchArea.next();
LOGGER.error("Branch Area Name is"+branchAreaObj.getBranchAreaName());
Iterator<Branch> itrBranch = branchAreaObj.getBranches().iterator();
while(itrBranch.hasNext()){
Branch branchObj = itrBranch.next();
LOGGER.error("Branch Name is"+branchObj.getBranchName());
}
}
branchAreaList Consist object of BranchArea. For Ftl i convert the branchAreaList into map
HashMap<String, List<BranchArea>> branchAreaMap = new HashMap<String, List<BranchArea>>();
branchAreaMap.put("branchAreaList", branchAreaList);
How can i iterate them in Ftl as i iterate it above

You can iterate over keys of your Map, and get the elements by this way:
<#list branchAreaMap?keys as key>
${key} = ${branchAreaMap[key])}
</#list>

Related

Java Stream group by one attribute and collect max element by another attribute

I am wondering if there is already an implemented feature in streams (or Collectors) which first groups a stream by an attribute and then returns the first element in the list sorted by another attribute. E.g. the following code tries to group a stream of objects using the first attribute and then wants to collect that object which has the highest value of the second attribute.
class MyClass{
String att1;
String att2;
}
Now, I want to achieve something like this with Stream myClassStream -
Map<String,MyClass> myMap = myClassStream().collect(Collectors.groupingBy(MyClass::getAtt1)); //Now I want to do Sorting after grouping to collect only the element which has the highest value of attr2.
My code using simple for loop is:
Map<String, MyClass> postAnalyticsMap = new HashMap<>();
for (MyClass post : myClassList) {
if (post.get(post.getAtt1()) == null) {
post.put(post.getAtt1(), post);
} else {
MyClass existingClass = postAnalyticsMap.get(post.getAtt1());
if (existingPostAnalytics.getAtt2() < post.getAtt2()) {
postAnalyticsMap.put(post.getAtt1(), post);
}
}
}
Any help will be much appreciated.
Use the toMap with merge function to find the max element on second attribute
Map<String, MyClass> map = myClassList.stream()
.collect(Collectors.toMap(MyClass::getAtt1, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(MyClass::getAtt2))));
You can do something like this:
myClassStream()
.collect(Collectors.groupingBy(MyClass::getAtt1,
Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparing(MyClass::getAtt2)),
myClass -> myClass.map(MyClass::getAtt2).orElse(""))));

Java Webdriver HashMap element array

String name = "";
String width = "";
String height = "";
List<WebElement> imageName = driver.findElements(By.cssSelector("div.card-arago div.hover-info div.name"));
List<HashMap> imageInfo = new ArrayList<HashMap>();
HashMap<String, String> attributes = new HashMap<String, String>();
imageInfo.add(attributes);
for (WebElement image : imageName) {
attributes.put("name",image.getText());
}
List<WebElement> images = driver.findElements(By.cssSelector("div.card-arago a img"));
for (WebElement image : images) {
attributes.put("width", image.getAttribute("width"));
attributes.put("height", image.getAttribute("height"));
}
I'm trying to return all the images from the page, but it only returns the last image card on the page?
A HashMap can only store one value with each key. If you call put with the same key more than once, each call overwrites the previous. You are calling attributes.put("name", ...) multiple times in a loop, so the value attached to the key "name" gets replaced over and over again, and at the end of the loop is just left with the last image. If you actually want all images to be returned, you either need unique keys for each image, or an entirely separate HashMap for each image, depending on how you want to structure this.
EDIT: after looking at your code a bit more, it looks like you do want a List of HashMaps. But you only ever add one single HashMap to that List. Instead, you could change that first loop to add a new HashMap for each image.
When calling put(k,v);, the key is stored and the value is the extra metadata. Just a key and a value.
If I call put(1, 2); and then call put(1, 3); the value returned by get(1); will be 3. the put(k,v); function only stores different objects within the HashMap. You can not have the same values within the same HashMap, however, you can have the same values within the same HashMap.
To solve your problem, I suggest you use an identifier such like
attributes.put("width" + someIntIdentifier, image.getAttribute("width");
You are using a map and keep updating the key values , for one key a map can have only one value (it replaces the previous value). Alternatively you may try using a List of map, which will contain your map containing info about image.
String name = "";
String width = "";
String height = "";
List imageNameList = new ArrayList(); // creating list to store imageName
List imageAttributesList = new ArrayList(); // creating list to store image height and width
List<WebElement> imageName = driver.findElements(By.cssSelector("div.card-arago div.hover-info div.name"));
List<HashMap> imageInfo = new ArrayList<HashMap>();
imageInfo.add(attributes);
for (WebElement image : imageName) {
HashMap<String, String> attributes = new HashMap<String, String>();
attributes.put("name",image.getText());
imageNameList.add(attributes); // adding map to list
}
List<WebElement> images = driver.findElements(By.cssSelector("div.card-arago a img"));
for (WebElement image : images) {
HashMap<String, String> attributes = new HashMap<String, String>();
attributes.put("width", image.getAttribute("width"));
attributes.put("height", image.getAttribute("height"));
imageAttributesList.add(attributes); // adding map to list
}
System.out.println(imageNameList); // this will give you a list of Map having "name" key
System.out.println(imageAttributesList); // this will give you a list of Map having "height" and "width" of image
Here I have created two List to store image name and height & width . Like this you can get attributes of all the images you needed.
If I understand what you're attempting to do, I agree with jthomas about returning a list of HashMaps. Additionally, rather than managing and looping a list of elements with the name text and then separately finding and looping the dimensions of the image element, you should be able to consolidate a bit if, I assume, both of those elements are within a common div. I would do something like this:
List<HashMap> images = new ArrayList<HashMap>();
List<WebElement> imageDivs = driver.findElements(By.cssSelector("div.card-arago");
for (WebElement imageDiv : imageDivs) {
HashMap<String, String> attributes = new HashMap<String, String>();
attributes.put("name", imageDiv.findElement(By.cssSelector("div.name").getText();
WebElement image = imageDiv.findElement(By.tagName("img");
attributes.put("width", image.getAttribute("width"));
attributes.put("height", image.getAttribute("height"));
images.add(attributes);
}
The images list would then give you a hashmap for each image card on the page, each of which contained the name, height, and width of that image. Then you could iterate that list as you please.
You could try using Multimap which stores multiple values for single key.
https://guava.dev/releases/23.0/api/docs/com/google/common/collect/Multimap.html

Check value inside Map

I have a Map where I save values with the form NAME-GROUP.
Before doing some operations, I need to know if the Map contains a specific group,
for example: I need to check for values containing group1 like Mark-group1.
I'm trying to get it this way:
if (checkList.containsValue(group1)) {
exists = true;
}
I can't provide the name when searching because there could be diferent names with the same group.
But it isn't finding the value, as seems that this function just looks for the entire value string and not only for part of it.
So, there would be any way of achieving this, or would I need to change the way I'm focusing my code.
Update--
This is the looking of my Map:
Map<Integer, String> checkList = new HashMap<Integer, String>();
I load some values from a database and I set them into the Map:
if (c.moveToFirst()) {
int checkKey = 0;
do {
checkKey++;
checkList.put(checkKey, c.getString(c.getColumnIndex(TravelOrder.RELATION)));
}while(c.moveToNext());
}
The relation column, has values like: mark-group1, jerry-group1, lewis-group2, etc...
So, the Map will have a structure like [1, mark-group1], etc...
What I need is to check if there is any value inside the map that contains the string group1 for example, I don't care about the name, I just need to know if that group exists there.
If you want to check any value contain your string as a substring you have to do the following:
for (String value : yourMap.values()) {
if (value.contains(subString)) {
return true;
}
}
return false;
By the way if your values in the map are really have two different parts, i suggest to store them in a structure with two fields, so they can be easily searched.

Storing Data in a HashMap Java

I am trying to store data in a HashMap however I can only seem to store the very last item of the data source I am reading into the HashMap and I am unsure why.
Below is my code:
//Loops through the counties and stores the details in a Hashmap
void getCountyDetails(List<Marker>m){
HashMap t = new HashMap();
for(Marker county: countyMarkers){
println("county:" + county.getProperties());
t = county.getProperties();
}
println(t);
}
This line -> println("county:" + county.getProperties());
Outputs this:
county:{name=Carlow, pop=54,612}
county:{name=Cavan, pop=73,183}
county:{name=Clare, pop=117,196}
county:{name=Cork, pop=519,032}
county:{name=Donegal, pop=161,137}
county:{name=Dublin, pop=1,273,069}
county:{name=Galway, pop=250,541}
county:{name=Kerry, pop=145,502}
county:{name=Kildare, pop=210,312}
county:{name=Kilkenny, pop=95,419}
county:{name=Laois, pop=80,559}
county:{name=Letrim, pop=31,796}
county:{name=Limerick, pop=191,809}
county:{name=Longford, pop=39,000}
county:{name=Louth, pop=122,897}
county:{name=Mayo, pop=130,638}
county:{name=Meath, pop=184,135}
county:{name=Monaghan, pop=60,483}
county:{name=Offaly, pop=76,687}
county:{name=Roscommon, pop=64,065}
county:{name=Sligo, pop=65,393}
county:{name=Tipperary, pop=158,754}
county:{name=Waterford, pop=113,795}
county:{name=Westmeath, pop=86,164}
county:{name=Wexford, pop=145,320}
county:{name=Wicklow, pop=136,640}
I would like to store them in a HashMap.
This line -> println(t); outputs:
{name=Wicklow, pop=136,640}
Would appreciate any help on the matter guys. Basically it's just getting the list of data into the hashmap and currently only the last item in that list is being placed in.
If you want to print the properties of each Marker , move the println(t) line into the for loop, because at the moment t will point to the last used element's properties, because you just reassign it;s value each iteration of the cycle. To put an element in the map, use put(Key, Value) or putAll() methods instead
In java, you should use hashMap.put(key, value) to add new item into hash map.
In your code, you wrote HashMap t = new HashMap(); t = county.getProperties(); so you map value is actually been reassigned to country property each time.

Change value of multidimensional ArrayList

I need a solution to change the value of an element in a multidimensional ArrayList in Java. This is my ArrayList:
public class Users {
ArrayList<ValidateUser> personer = new ArrayList<ValidateUser>();
public Users() {
personer.add(new ValidateUser("admin", "asdf123", 0.8, "admin"));
personer.add(new ValidateUser("jesper", "ukamm19", 2.5, "user"));
personer.add(new ValidateUser("lars", "lol123", 1.5, "user"));
}
I want to change the double value (0.8) at the user "admin", for example.
This would be done from another a class.
How to do so?
Thanks in advance! :)
As I've stated in my comment, just iterate through the list to find the object. If you're going to do this a lot, consider using a map.
for (ValidateUser user : personer)
if (user.getName().equals("admin"))
user.setNumber(someNumber);
First, note that this is not a multidimensional array, is just a list that holds elements of ValidateUser class object references. Second, you need to access to the element before updating it. You have several ways to accomplish this:
Implement the equals and hashCode methods in your ValidateUser class, then just retrieve the object from your List:
ValidateUser adminUser = personer.get(new ValidateUser("admin", "", 0.8, ""));
adminUser.set...
Note: this looks ridiculous but will work (assuming your equals method only checks by the field that holds this "admin" value.
Navigate through the array and seek for the desired element manually, then update it:
for (ValidateUser user : personer) {
if ("admin".equals(user.getXxx()) {
user.set...
break; //don't forget this!
}
}
Use a different data structure like a Map<String, ValidateUser> to store your data and faster retrieval:
Map<String, ValidateUser> personerMap = new LinkedHashMap<String, ValidateUser>();
personerMap.add("admin", new ValidateUser("admin", ...);
//fill the map with other values...
//if you still want a Collection<ValidateUser> personer variable
Collection<ValidateUser> personer = personerMap.values();
//now check for the desired element
ValidateUser admin = personerMap.get("admin");
if (admin != null) {
admin.set...
}
By comments, your ValidateUser is an immutable object, so you cannot update its fields using setters (because there aren't). So, the best approach here is to use a ListIterator<ValidateUser> instead (not to confuse with Iterator) and replace the element by your modified object. Here's an example:
//the new immutable ValidateUser that will replace the older one...
//set the parameters as needed
ValidateUser newAdmin = new ValidateUser("admin", ...);
ListIterator<ValidateUser> listIterator = personer.listIterator();
while (listIterator.hasNext()) {
ValidateUser validateUser = listIterator.next();
if ("admin".equals(validateUser.getXxx()) {
listIterator.set(newAdmin);
break;
}
}

Categories

Resources