Problem with List - java

I am a java newbie, and having some issue with "java.util.List".Below is my code,where I'm trying to create a list of objects but the result I am getting is undesired.Can you please help me in solving the issue.
import java.util.*;
class testMap
{
public static void main(String[] args)
{
HashMap<String,Object> childRowMap = new HashMap<String, Object>();
List <Object> actList= new ArrayList <Object> ();
for (int x=0;x<2 ;x++ ){
if(x==0){
childRowMap.put("startDate","startDate"+x);
childRowMap.put("endDate","endDate"+x);
childRowMap.put("encodedValue"," enc"+x);
}
else if (x==1){
childRowMap.put("startDate","startDate"+x);
childRowMap.put("endDate","endDate"+x);
childRowMap.put("encodedValue"," enc"+x);
}
System.out.println("Adding object in the postition "+ x);
actList.add(x,childRowMap);
}
System.out.println(actList);
}
}
Result:
Adding object in the postition 0
Adding object in the postition 1
[{encodedValue= enc1, startDate=startDate1, endDate=endDate1}, {encodedValue= en
c1, startDate=startDate1, endDate=endDate1}]
===============
Why I am not getting objects with different values.Kindly helping me out in figuring the problem with my code..

You're adding childRowMap twice.
Note that you're adding the reference to childRowMap. This means that changes to the map will be visible from both reference at index 0 and index 1, and that's why it looks like you've added two identical objects.
You could fix it by creating a new map each iteration in the loop:
import java.util.*;
class testMap {
public static void main(String[] args) {
.-------
|
| List<Object> actList = new ArrayList<Object>();
|
| for (int x = 0; x < 2; x++) {
|
'---------> HashMap<String, Object> childRowMap = new HashMap<String, Object>();
if (x == 0) {
childRowMap.put("startDate", "startDate" + x);
childRowMap.put("endDate", "endDate" + x);
childRowMap.put("encodedValue", " enc" + x);
} else if (x == 1) {
childRowMap.put("startDate", "startDate" + x);
childRowMap.put("endDate", "endDate" + x);
childRowMap.put("encodedValue", " enc" + x);
}
System.out.println("Adding object in the postition " + x);
actList.add(x, childRowMap);
}
System.out.println(actList);
}
}
Output:
Adding object in the postition 0
Adding object in the postition 1
[{encodedValue= enc0, startDate=startDate0, endDate=endDate0},
{encodedValue= enc1, startDate=startDate1, endDate=endDate1}]

You need to reinitialize your map on every iteration. Put the initialization inside the for loop:
for(int x = 0; x < 2; x++) {
HashMap<String,Object> childRowMap = new HashMap<String, Object>();
...
}

The problem is that childRowMap is the same instance, created in your first line of code. When you go through the for loop, you aren't creating a new instance, you're just putting new values in the existing HashMap. That means that the ArrayList, performing a referential check, sees that the object is already in the list and doesn't add it twice.
Simple fix: move the initialization inside the for loop, so on each iteration through the loop, the HashMap is re-instantiated.
class testMap {
public static void main(String[] args) {
HashMap<String,Object> childRowMap;
List <Object> actList= new ArrayList <Object> ();
for (int x=0;x<2 ;x++ ){
childRowMap = new HashMap<String, Object>();
if(x==0){
childRowMap.put("startDate","startDate"+x);
childRowMap.put("endDate","endDate"+x);
childRowMap.put("encodedValue"," enc"+x);
} else if (x==1){
childRowMap.put("startDate","startDate"+x);
childRowMap.put("endDate","endDate"+x);
childRowMap.put("encodedValue"," enc"+x);
}
System.out.println("Adding object in the postition "+ x);
actList.add(x,childRowMap);
}
System.out.println(actList);
}
}

There are many issues in your code. It can all be compacted like this:
List <Map<String,Object>> actList= new ArrayList<Map<String,Object>> ();
for (int x=0;x<2 ;x++ ){
Map<String,Object> childRowMap = new HashMap<String, Object>();
childRowMap.put("startDate","startDate"+x);
childRowMap.put("endDate","endDate"+x);
childRowMap.put("encodedValue"," enc"+x);
System.out.println("Adding object in the postition "+ x);
actList.add(childRowMap);
}
System.out.println(actList);
Few other things:
As a Java standard your class name should start with upper case so consider TestMap instead of testMap
Type of Map variable should be generic Map instead of an implementation like HashMap (I have corrected that in my answer).
Consider declaring List as of more specific type List<Map<String,Object>> instead of generic Object for type safety.

As others said, hash map keys should be unique, simplest fix is add this line
HashMap<String,Object> childRowMap = new HashMap<String, Object>();
at the start of the for-loop

Maps store by Key:Value pairs. In your code when you do
childRowMap.put("startDate","startDate"+x)
it is doing this:
childRowMap.put(Key,Value)
So basically you are setting the key startDate to be equal to startDate0 (when x is 0). When you loop through the second time, you are setting the key startDate to be equal to startDate1 (because x is 1). Now whenever you look up startDate, it will only have startDate1 stored because startDate0 was overwritten because you only have 1 Map.
You can fix this by either reinitializing your Map every time you loop through or by using new and unique Key's to each Value you put in the Map.

Related

How to retrieve data from nested dictionary in java

I have two dictionaries added into parent dictionary. How to retrieve data from a value (which is a dictionary)
import java.util.*;
class HelloWorld {
public static void main(String[] args) {
int count =2;
Dictionary parent_dic = new Hashtable();
Dictionary child1 = new Hashtable();
Dictionary child2 = new Hashtable();
Dictionary child = new Hashtable();
child1.put("1", "one");
child1.put("2", "two");
System.out.println("Child1" + child1);
child2.put("3", "three");
child2.put("4", "four");
System.out.println("Child2" + child2);
for(int each_c = 1; each_c <= count; each_c++) {
if(each_c==1) {
child = child1;
} else {
child = child2;
}
parent_dic.put(each_c,child);
}
System.out.println("Parent" + parent_dic);
System.out.println("test ::: " + parent_dic.get(1));
}
}
How to get value from resultant value (which is dictionary)?
Output:
Child1{2=two, 1=one}
Child2{4=four, 3=three}
Parent{2={4=four, 3=three}, 1={2=two, 1=one}}
test ::: {2=two, 1=one}
How to get value "two" from above test dictionary.
I tried to rewrite your code in a way that made more sense to me.
I've added the use of proper types as well, using raw types in java is dangerous. The last line of my code does what I believe you want. Note the difference between using Integers as keys and Strings as keys.
public static void main(String[] args) {
Dictionary<Integer, Dictionary> parent_dic = new Hashtable();
Dictionary<String, String> child1 = new Hashtable();
Dictionary<String, String> child2 = new Hashtable();
child1.put("1", "one");
child1.put("2", "two");
System.out.println("Child1" + child1);
child2.put("3", "three");
child2.put("4", "four");
System.out.println("Child2" + child2);
parent_dic.put(1, child1);
parent_dic.put(2, child2);
System.out.println("Parent" + parent_dic);
System.out.println("test : " + parent_dic.get(1));
System.out.println("two : " + parent_dic.get(1).get("2"));
}
You need to add generic types to your variable declarations (e.g. Dictionary<Integer, Dictionary> parent_dic = new HashTable<Integer, Dictionary>();)
Without them the compiler tries to add them in, not always successfully. The key and value pairs for your parent_dic, child1, and child2 have defaulted to Object. You can add anything to them, even a Random object or an ArrayList. If you try to access the output of your last line by adding .get("1") it won't compile, because you are trying to use get("1") on an Object.
If you add the types, like Dictionary<Integer, Dictionary> you can access the data in the child dictionaries.

Java Map Adding Key Values

Method :
public void itemAmountCollection() {
Map<String, List<Integer>> orderItemDetails = new LinkedHashMap<String, List<Integer>>();
ArrayList<Integer> itemsAmount = new ArrayList<Integer>();
WebElement orderItemTable = driver.findElement(By
.xpath("//*[#id='tblInfo']/tbody"));
List<WebElement> noOfItems = orderItemTable.findElements(By
.tagName("tr"));
for (int i = 1; i <= noOfItems.size(); i++) {
String itemAmount = driver.findElement(
By.xpath("//*[#id='tblInfo']/tbody/tr[" + i
+ "]/td[8]")).getText();
itemsAmount.add(Integer.parseInt(itemAmount));
orderItemDetails.put("amount", itemsAmount);
}
}
with above method we collected all the item amount with Map Collections and Output for the above method is (345,7905,345)
how can we add all the values in an particular Key (amount)
Expected Output :
8595 (i.e 345+7905+345)
I don't really get what you mean, but I'm amusing that you're trying to add all values in a List. To do this:
int result = 0;
for(int i : itemsAmount)
{
result+=1;
}
System.out.println(result);//This should print 8595.
In general Map<Key,List<Value>> structures end up needing code that looks as follows:
public addValue(Key key, Value value) {
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(value);
}
In your case you should replace orderItemDetails.put with similar code.
Alternatively you could use a true Multimap from a third party library such as guava.
Summing the values would simply be:
map.get(key).stream().sum();
Assuming that the values are List which makes the stream an IntStream.

Update an ArrayList<Station> with values from a TreeMap<Integer, ArrayList<Station>>

I need to replace the outdated objects in ArrayList<Station> with the updated objects in TreeMap<Integer, ArrayList<Station>>.
TreeMap> only has a portion of the Station objects in ArrayList.
Anyone know a way to do this in a fast and smooth way? My application is time sensitive, the faster it can process it the better it is due to the big amount of data it is processing.
I can post here the code I've if it is of any help
EDIT:
Here's the code:
public ArrayList<Station> smoothPingPong(ArrayList<Station> dados){
ArrayList<Station> pingPongs = new ArrayList<>();
TreeMap<Integer, ArrayList<Station>> tmap = new TreeMap<>();
int tmap_key = 0;
for(int i = 0; i<dados.size(); i++) {
if(dados.get(i).getPingPong() == 1) {
pingPongs.add(dados.get(i));
}
}
ArrayList<Station> next = new ArrayList<Station>();
for(Station d : pingPongs) {
if(!next.isEmpty() && next.get(next.size() - 1).getId() != d.getId() - 1) {
tmap.put(tmap_key++, next);
next = new ArrayList<Station>();
}
next.add(d);
}
if(!next.isEmpty()) {
tmap.put(tmap_key++, next);
}
for(Integer a : tmap.keySet()){
//Processes the treemap updating it
}
}
Now I need to go back to the Stations in the ArrayList dados and update it with the Stations I've on the TreeMap.
Because you are not creating new Station Objects then you don't need to update anything, the station objects share the same reference in all your collections.
In this case, you are just returning a subset of the Station Collection, but the objects themselves are the same.

Adding to hashmap and arraylist

I am trying to add hashmaps to array list.
But the map(completeEntrie) is overriding the previous values when I am trying to add more than one value to arraylist(listOfCompleteEntries)
public class MapExample {
public static void main(String a[]) {
ArrayList listOfCompleteEntries = new ArrayList();
Map<String, String> completeEntrie = new HashMap<String, String>();
for (int i = 0; i < 3; i++) {
completeEntrie.put("KEY_NAME", "Number:" + i);
System.out.print(completeEntrie.toString());
listOfCompleteEntries.add(completeEntrie);
System.out.println(listOfCompleteEntries.toString());
}
System.out.println(listOfCompleteEntries.toString());
}
}
Output for the above code is
{KEY_NAME=Number:0}[{KEY_NAME=Number:0}]
{KEY_NAME=Number:1}[{KEY_NAME=Number:1}, {KEY_NAME=Number:1}]
{KEY_NAME=Number:2}[{KEY_NAME=Number:2}, {KEY_NAME=Number:2}, {KEY_NAME=Number:2}]
[{KEY_NAME=Number:2}, {KEY_NAME=Number:2}, {KEY_NAME=Number:2}]
But i want the output to be like this
{KEY_NAME=Number:0}[{KEY_NAME=Number:0}]
{KEY_NAME=Number:1}[{KEY_NAME=Number:0}, {KEY_NAME=Number:1}]
{KEY_NAME=Number:2}[{KEY_NAME=Number:0}, {KEY_NAME=Number:1}, {KEY_NAME=Number:2}]
[{KEY_NAME=Number:0}, {KEY_NAME=Number:1}, {KEY_NAME=Number:2}]
Also please explain why is this map overriding the previous map in arraylist.
Thanks for your help.
Despite the irrelevant title, you need to construct a new map instance for each unique entry you want to add to the array list. Without this, you are modifying the same map instance.

Java HashMap content seems to change without changing it

I have a problem concerning a HashMap in Java. To explain the problem in a detailed way, i will first post some code you can refer to.
public void BLASTroute(String args[]) throws IOException, InterruptedException{
...
correctMapping CM = new correctMapping();
CM.correctMapping(RB.BLASTresults, exists);
CalculateNewConsensusSequence CNCS =
new CalculateNewConsensusSequence();
char[] consensus = CNCS.calculateNewConsensusSequence(
CM.newSeq, CM.remindGaps, EMBLreaderReference.sequence, exists);
HashMap<Integer, ArrayList<String>> gapsFused =
new HashMap<Integer, ArrayList<String>>();
for (Integer i : CM.remindGaps.keySet()) {
ArrayList<String> newList = CM.remindGaps.get(i);
gapsFused.put(i, newList);
}
GenerateGeneLists GGL = new GenerateGeneLists(
EMBLreaderReference, CM.newSeq, gapsFused, exists,
GQList, allMappedPositions);
System.out.println(CM.remindGaps.hashCode());
gapsFused=GGL.generateGeneListSNP(gapsFused);
System.out.println(CM.remindGaps.hashCode());
System.out.println(gapsFused.hashCode());
GGL.generateGeneListFrameShift(gapsFused);
}
The following occurs:
in my class correctMapping, i fill a global variable called remindGaps. I use it later in some functions, and nothing happens/everything works as expected.
Then, i make a copy of the HashMap called gapsFused (i don't know if this has something to do with my problem).
Now comes the interesting part: In the class GenerateGeneLists, i don't do a thing with the remindGaps HashMap.
However, after the function generateGeneListSNP is performed, remindGaps changed! I'll post the code for you as well, so that you can help me better:
public GenerateGeneLists(EMBL_reader EMBLreaderReference,
HashMap<String,ArrayList<String>> newSeq,
HashMap<Integer,ArrayList<String>> gapsFused, File exists,
ArrayList<GeneQualifier> GQlist,
HashMap<Integer,Integer> allMappedPositions)
throws InterruptedException{
this.EMBLreaderReference=EMBLreaderReference;
this.newSeq=newSeq;
//this.gapsFused=gapsFused;
this.exists=exists;
this.GQlist=GQlist;
this.allMappedPositions=allMappedPositions;
for (GeneQualifier GQ : this.GQlist){
startlist.add(GQ.start);
stoplist.add(GQ.stop);
startMap.put(GQ.start,GQ);
}
}
public HashMap<Integer,ArrayList<String>> generateGeneListSNP(
HashMap<Integer,ArrayList<String>> gapsFused)
throws IOException{
File GQSNP = new File (exists+"/GQsnp.txt");
BufferedWriter SNP = new BufferedWriter(new FileWriter(GQSNP));
SNP.write("#Gene_start\tGene_stop\tlocus_tag\tproduct" +
"\tputative_SNP_positions(putative_changes)\n");
HashMap<GeneQualifier,ArrayList<Integer>> GQreminder =
new HashMap<GeneQualifier,ArrayList<Integer>>();
for (String s : newSeq.keySet()){
ArrayList<String> blub = newSeq.get(s);
char[] qrySeq = blub.get(0).toCharArray();
char[] refSeq = blub.get(1).toCharArray();
int start = Integer.valueOf(blub.get(2));
int stop = Integer.valueOf(blub.get(3));
for (int i=0;i<refSeq.length;i++){
if (qrySeq[i]!=refSeq[i]&&qrySeq[i]!='-'&&qrySeq[i]!='.'){
if (mismatchList.containsKey(start+i)){
ArrayList<Character> blah = mismatchList.get(start+i);
blah.add(qrySeq[i]);
mismatchList.put(start+i, blah);
}
else {
ArrayList<Character> blah = new ArrayList<Character>();
blah.add(qrySeq[i]);
mismatchList.put(start+i,blah);
}
}
else if (qrySeq[i]!=refSeq[i]&&(qrySeq[i]=='-'||qrySeq[i]=='.')){
if (!gapsFused.containsKey(start+i)){
ArrayList<String> qwer = new ArrayList<String>();
qwer.add(String.valueOf(qrySeq[i]));
gapsFused.put(start+i,qwer);
}
else {
ArrayList<String> qwer = gapsFused.get(start+i);
qwer.add(String.valueOf(qrySeq[i]));
gapsFused.put(start+i,qwer);
}
if (!deletionPositionsAndCount.containsKey((start+i))){
int count = 1;
deletionPositionsAndCount.put(start+i, count);
}
else {
int count = deletionPositionsAndCount.get(start+i);
count = count+1;
deletionPositionsAndCount.put(start+i, count);
}
}
}
}
for (Integer a : mismatchList.keySet()){
for (int i=0;i<startlist.size();i++){
int start = startlist.get(i);
int stop = stoplist.get(i);
if (a>=start && a<=stop){
GeneQualifier GQ = startMap.get(start);
if (!GQreminder.containsKey(GQ)){
ArrayList save = new ArrayList<Integer>();
save.add(a);
GQreminder.put(GQ,save);
}
else {
ArrayList save = GQreminder.get(GQ);
save.add(a);
GQreminder.put(GQ,save);
}
break;
}
}
}
for (GeneQualifier GQ : GQreminder.keySet()) {
ArrayList<Integer> save = GQreminder.get(GQ);
int start = GQ.start;
int stop = GQ.stop;
String locus_tag =
GQ.geneFeatures.get("locus_tag").get(0).replace("\n", "");
String product =
GQ.geneFeatures.get("product").get(0).replace("\n", "");
SNP.write(start + "\t" + stop + "\t" + locus_tag +
"\t" + product + "\t");
boolean end = false;
for (int i = 0; i < save.size(); i++) {
if (i==save.size()-1) end=true;
int posi = save.get(i);
SNP.write(posi + "(");
ArrayList<Character> mismatches = mismatchList.get(posi);
for (int j = 0; j < mismatches.size(); j++) {
char snipp = mismatches.get(j);
if (j == mismatches.size() - 1) {
SNP.write(snipp + ")");
} else {
SNP.write(snipp + ",");
}
}
if (end == false){
SNP.write(",");
}
}
SNP.write("\n");
}
SNP.close();
return gapsFused;
}
As you can see, remindGaps is not used in this class, but still it undergoes changes. Do you have an idea why this is the case?
What I tested is, whether remindGaps changes if i manually change gapsFused (the made copy of the first HashMap). This is not the case, so i don't think that the copying process went wrong (for example only points to the other HashMap or references it).
I would really appreciate your ideas and help in order to solve this problem.
You have to remember that in Java all objects are passed as reference. So, when you did:
ArrayList<String> newList = CM.remindGaps.get(i);
you basically pointed newList to the same list as contained in the remindGaps map. Now, even though you work with the gapsFused, any changes to its values effect the same underlying list in the memory - to which both remindGaps and gapsFused are pointing.
Change your copy code to the following and see if it makes a difference:
ArrayList<String> newList = new ArrayList<String>(CM.remindGaps.get(i));
By doing this, you are creating a new list that newList will be pointing to and thus the changes will be encapsulated.
Your code is very long and hard to read (mainly because it doesn't respect Java naming conventions), but my guess is that your problem comes from the fact that your copy of the map simply copies the ArrayList references from one map to another:
HashMap<Integer, ArrayList<String>> gapsFused = new HashMap<Integer, ArrayList<String>>();
for (Integer i : CM.remindGaps.keySet()) {
ArrayList<String> newList = CM.remindGaps.get(i);
gapsFused.put(i, newList);
}
In the above code, you don't create any new list. You just store the same lists in another map. If you need a new list, the code should be:
Map<Integer, List<String>> gapsFused = new HashMap<Integer, List<String>>();
for (Integer i : CM.remindGaps.keySet()) {
List<String> newList = new ArrayList<STring>(CM.remindGaps.get(i));
gapsFused.put(i, newList);
}
Without analyzing all your code:
HashMap<Integer, ArrayList<String>> gapsFused = new HashMap<Integer, ArrayList<String>>();
for (Integer i : CM.remindGaps.keySet()) {
ArrayList<String> newList = CM.remindGaps.get(i);
gapsFused.put(i, newList);
}
After this code gapFused will contain entries that are copies of the entries of remindGaps, therefore those entries will reference the same objects (key and values). So if you add or remove entries in one Map it will have no effect on the other, but if you change a value accessing it through one Map you will see the change also accessing it through the other map (for example remingGaps.get(1).add("hello")).
The name "newList" used in your code is confusing because it is not a new list, just a reference on an existing one...
Since the value of the Map is an ArrayList and you are doing just a shallow copy (meaning the new Map has a reference to the same Lists as are in the first Map) and changes to the lists in the second map would be reflected in the first map. To avoid this you would need to make deep copies of the lists when you create the new Map.

Categories

Resources