I'm using List of Map in java but I get a trouble. I use :
Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
ArrayList<Map<String,AttributeValue>> maps = new ArrayList<Map<String,AttributeValue>>();
I use CSVReader to reading file and store values in ListOfMap
CSVReader reader = new CSVReader(new FileReader("data1.csv"));
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
item.clear();
item.put("Id", new AttributeValue().withN(nextLine[0]));
item.put("Name", new AttributeValue().withS(nextLine[1]));
System.out.println("Item:"+item); // I try printing item
maps.add(item);
}
And Result is :
Item:{Id={N: 0,}, Name={S: goGOv,}}
Item:{Id={N: 1,}, Name={S: TBlGD,}}
Item:{Id={N: 2,}, Name={S: OtXuw,}}
...
Item:{Id={N: 999,}, Name={S: QAMzc,}}
Item:{Id={N: 1000,}, Name={S: PumAq,}}
But when I print some element from this List
System.out.println(" "+maps.get(i)); // I tried i from 0-1000
It always show only 1 ouput
{Id={N: 1000,}, Name={S: PumAq,}}
So anyone can show me where I'm wrong.
Thank you,
You are using same map to store all elements, but at start of each iteration you are calling item.clear(); which removes previously stored elements inside map. What you should do is create new, separate map instead of reusing old one, so change
item.clear();//don't reuse previously filled map because it still is the same map
into
item = new HashMap<>();//use separate map
You keep using the same Map object. These are persistant objects. You'll have to instantiate a new HashMap() instead of calling clear() on the existing one.
Otherwise you'll simply clear the HashMap inside of the List as well, because they refer to the same object.
Related
I have a problem with my Java Code. I want to store multiple Values in one Key but I want to store them flexible. This means I read from a textfile and every line is one word. To store them, I want to build pairs of words. For example:
word1/word2
word2/word3
word3/word4
I have changed this method a little bit. I want to store the values of the keys in an arraylist. This means everytime when a new key comes up a new Arraylist and key will be stored, but if the key is in the map I want to store them in the list of this key. Is this possible?
We have to store them in a hashmap. But I can not get it to work:
private HashMap<String, ArrayList<String>> hmap = new HashMap<String, ArrayList<String>>();
private ArrayList<String> wort2;
public GrammelotH(String filename) throws IOException {
String fixWort = ".";
BufferedReader br = new BufferedReader(new FileReader(filename));
while (br.ready()) {
String line = br.readLine();
if (hmap.containsKey(fixWort)) {
hmap.put(fixWort, wort2.add(line));
}else {
hmap.put(fixWort, new ArrayList<String>().add(line));
}
fixWort = line;
}
br.close();
}
The problem is the put order. Has anybody of you an idea how to get
hmap.put(fixWort, new ArrayList<String>().add(line));
and
hmap.put(fixWort, wort2.add(line));
to work?
Thank you for your help!
Bye Bye!
I think I'd be looking at something like
List l = hmap.get(line);
if (l != null) {
l.add(line));
}else {
l = new ArrayList<String>();
l.add(line)
hmap.put(line, l);
}
So, you see if the map already contains the line you have just read from the file. If it does, you just add it to the associated list. If it doesn's.create a list, add line to it, and then add both to the Map.
When I wrote this piece of code due to the pnValue.clear(); the output I was getting was null values for the keys. So I read somewhere that adding values of one map to the other is a mere reference to the original map and one has to use the clone() method to ensure the two maps are separate. Now the issue I am facing after cloning my map is that if I have multiple values for a particular key then they are being over written. E.g. The output I am expecting from processing a goldSentence is:
{PERSON = [James Fisher],ORGANIZATION=[American League, Chicago Bulls]}
but what I get is:
{PERSON = [James Fisher],ORGANIZATION=[Chicago Bulls]}
I wonder where I am going wrong considering I am declaring my values as a Vector<String>
for(WSDSentence goldSentence : goldSentences)
{
for (WSDElement word : goldSentence.getWsdElements()){
if (word.getPN()!=null){
if (word.getPN().equals("group")){
String newPNTag = word.getPN().replace("group", "organization");
pnValue.add(word.getToken().replaceAll("_", " "));
newPNValue = (Vector<String>) pnValue.clone();
annotationMap.put(newPNTag.toUpperCase(),newPNValue);
}
else{
pnValue.add(word.getToken().replaceAll("_", " "));
newPNValue = (Vector<String>) pnValue.clone();
annotationMap.put(word.getPN().toUpperCase(),newPNValue);
}
}
sentenceAnnotationMap = (LinkedHashMap<String, Vector<String>>) annotationMap.clone();
pnValue.clear();
}
EDITED CODE
Replaced Vector with List and removed cloning. However this still doesn't solve my problem. This takes me back to square one where my output is : {PERSON=[], ORGANIZATION=[]}
for(WSDSentence goldSentence : goldSentences)
{
for (WSDElement word : goldSentence.getWsdElements()){
if (word.getPN()!=null){
if (word.getPN().equals("group")){
String newPNTag = word.getPN().replace("group", "organization");
pnValue.add(word.getToken().replaceAll("_", " "));
newPNValue = (List<String>) pnValue;
annotationMap.put(newPNTag.toUpperCase(),newPNValue);
}
else{
pnValue.add(word.getToken().replaceAll("_", " "));
newPNValue = pnValue;
annotationMap.put(word.getPN().toUpperCase(),newPNValue);
}
}
sentenceAnnotationMap = annotationMap;
}
pnValue.clear();
You're trying a bunch of stuff without really thinking through the logic behind it. There's no need to clear or clone anything, you just need to manage separate lists for separate keys. Here's the basic process for each new value:
If the map contains our key, get the list and add our value
Otherwise, create a new list, add our value, and add the list to the map
You've left out most of your variable declarations, so I won't try to show you the exact solution, but here's the general formula:
List<String> list = map.get(key); // try to get the list
if (list == null) { // list doesn't exist?
list = new ArrayList<>(); // create an empty list
map.put(key, list); // insert it into the map
}
list.add(value); // update the list
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
I've been trying to group of facets by translated value, but what I always get is only one last object on the List (no dataset). Here is what I tried:
HashMap<String, List<Facet>> map = new HashMap<>();
for (Facet facet : getFacets()) {
map.put(facet.getTranslatedValue(), new ArrayList<com.schneider.gss.model.Facet>());
map.get(facet.getTranslatedValue()).add(facet);
}
Can you suggest anything?
Change your for loop as below
for (Facet facet : getFacets()) {
if(map.get(facet.getTranslatedValue()) == null) {
map.put(facet.getTranslatedValue(), new ArrayList<com.schneider.gss.model.Facet>());
}
map.get(facet.getTranslatedValue()).add(facet);
}
You're overwriting your list each time you get an identical translated value with a new ArrayList. Instead, you should check if it exists:
HashMap<String, List<Facet>> map = new HashMap<>();
for (Facet facet : getFacets()) {
//get the list
ArrayList<com.schneider.gss.model.Facet> list = map.get(facet.getTranslatedValue());
//if list doesn't exist, create it
if(list == null) {
map.put(facet.getTranslatedValue(), new ArrayList<com.schneider.gss.model.Facet>());
}
//then add to list
map.get(facet.getTranslatedValue()).add(facet);
}
in Guava there is class Multimap (or ArrayListMultimap) which does exactly what you need
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>