Java Map Adding Key Values - java

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.

Related

How to create a HashMap that would have String as key and the value would be another HashMap from one list of custom object?

I have a list of custom object,
public class Assignmentsdata {
String assignmentId;
String teacherId;
String groupName;
String sectionId;
String levelId;
String startTime;
}
ArrayList<Assignmentsdata> list = new ArrayList<>();
lets say there are 20 elements in that list.
Now I want to get the output which is a hashmap of startTime as a key and the Value would be a new HashMap of GroupID and a list of Assignments of those that had the same groupName.
OutPut Example
HashMap<startTime,HasMap<groupName,List> hashMap = new HashMap();
a little more insight about the problem: First I want to categorise based on startTime(Month) then i want to categorise based on groupName, Thanks in advance.
I have successfully categorised based on group name and created a map through below code:
for( int i = 0; i<assignmentsdataArrayList.size();i++ ){
if (hashMap.size()>0){
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}else {
hashMap.put(assignmentsdataArrayList.get(i).getGroupName(),new ArrayList<Assignmentsdata>());
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
}
After that I am lost on how to categorise this hashmap based on the startDate and create a hashmap that would look like the above hashmap in the output heading.
your code may throw a NullPointerException at the first if branch
if (hashMap.size()>0)
{hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
the map.size()>0 doesnt means the Value of GroupName has put a new ArrayList already.
the anwser of using loop should like this
Map<String, Map<String, List<Assignmentsdata>>> map = new HashMap<>();
for (Assignmentsdata assignmentsdata : list) {
if (!map.containsKey(assignmentsdata.getStartTime())) {
map.put(assignmentsdata.getStartTime(), new HashMap<>());
}
Map<String, List<Assignmentsdata>> startTimeMap = map.get(assignmentsdata.startTime);
if (!startTimeMap.containsKey(assignmentsdata.getGroupName())) {
startTimeMap.put(assignmentsdata.getGroupName(), new ArrayList<>());
}
startTimeMap.get(assignmentsdata.groupName).add(assignmentsdata);
}
or you could use the java stream().collect(Collectors.groupingBy()) api to get the result easily
Map<String, Map<String, List<Assignmentsdata>>> result = list.stream()
.collect(Collectors.groupingBy(Assignmentsdata::getStartTime,Collectors.groupingBy(Assignmentsdata::getGroupName)));
I am answering my own question as I solved it if anyone has a better answer please passed your answer aswell, ill accept another answer suitable and efficient answer.
for( int i = 0; i<assignmentsdataArrayList.size();i++ ){
if (hashMap.size()>0){
if (hashMap.get(assignmentsdataArrayList.get(i).getGroupName())==null){
hashMap.put(assignmentsdataArrayList.get(i).getGroupName(),new ArrayList<Assignmentsdata>());
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}else{
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
}else {
hashMap.put(assignmentsdataArrayList.get(i).getGroupName(),new ArrayList<Assignmentsdata>());
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
}
// above part is already in the question. the second part i looped through the hashMap then the list once again, and checking if list and map entry have same group name, then made the startdate key that indexed element from the list.
HashMap<String, Map.Entry<String, ArrayList<Assignmentsdata>>> hashMapHashMap = new HashMap<>();
for (var entry : hashMap.entrySet()){
for( int j = 0; j<assignmentsdataArrayList.size();j++ ){
if (assignmentsdataArrayList.get(j).getGroupName()==entry.getKey()){
hashMapHashMap.put(assignmentsdataArrayList.get(j).getStartTime(),entry);
}
}
hashMapHashMap.put(entry.getValue().get())
}

JAVA Iterateing through Hasmap with list

I need iterate through hashmap and get key value which should be a string and all values within that key which is a list of strings that have strings?
Psuedo code
static HashMap<String, List<String>> vertices = new HashMap<String, List<String>>();
for (int i = 0; i < vertices.size(); i++)
{
String key = vertices.getKey at first postions;
for (int x = 0; x < size of sublist of the particular key; x++)
{
String value = vertices key sublist.get value of sublist at (i);
}
}
You can't iterate over HashMap directly, as there is no numeric index of values within HashMap. Instead key values are used, in your case of type String. Therefore the values don't have a particular order. However, if you want, you can construct a set of entries and iterate over that, using vertices.entrySet().
for (Entry<String, List<String>> item : vertices.entrySet()) {
System.out.println("Vertex: " + item);
for (String subitem : item.getValue()) {
System.out.println(subitem);
}
}
Try vertices.keySet();
It gives a Set of all keys in the map. Use it in a for loop like below
for (String key : vertices.keySet()) {
for (String value : vertices.get(key)) {
//do stuff
}
}

write data from hashmap as a CSV file

Say I have a hashmap with String type as key and ArrayList type as value, example {"value1"=["one","three","five"], "value2"=["two","four","six"]} where "value1" and "value2" are keys. I want to write the above hashmap data in following format. (so that I can read the csv file in excel)
value1,value2
one,two
three,four
five,six
My idea was to write the first key and its values as follows
value1
one
three
five
Then I was thinking of using the seek method in RandomAccessFile class to back to line 1 and again write the second key and its values. However I am not able to accomplish this task since seek function takes in the length of strings in the entire file and writes the new string after it. While I wanted the pointer to jump to the first line and append the string. Is there a better way to do this?. A quick example would be much appreciated.
Thanks
Why can't you just use 4 Strings, one for each row? Something like this:
StringBuilder keyRow = new StringBuilder();
StringBuilder value1 = new StringBuilder();
StringBuilder value2 = new StringBuilder();
StringBuilder value3 = new StringBuilder();
Iterator keys = hashmap.keySet().iterator();
boolean notFirst = true;
while(keys.hasNext()) {
String key = (String)keys.next();
ArrayList list = (ArrayList)hashmap.get(key);
if(!notFirst) {
keyRow.append(",");
value1.append(",");
value2.append(",");
value3.append(",");
}
keyRow.append(key);
value1.append((String)list.get(0));
value2.append((String)list.get(1));
value3.append((String)list.get(2));
notFirst = false;
}
Then at the end, just take the 4 Strings
String csv = keyRow.toString()+"\n"+value1.toString()+"\n"+value2.toString()+"\n"+value3.toString();
Note that this example isn't really proper CSV. Strings with commas aren't wrapped in quotes.
Or you iterate through the HashMap a thousand times if you have thousands of these rows. To save a bit of time from looking up a key, you can put them all in an ArrayList:
StringBuilder csv = new StringBuilder();
int row = 0;
ArrayList<ArrayList> list = new ArrayList<ArrayList>();
// Write the keys row:
Iterator keys = hashmap.keySet().iterator();
boolean notFirst = true;
while(keys.hasNext()) {
String key = (String)keys.next();
ArrayList tmp = (ArrayList)hashmap.get(key);
if(!notFirst) {
csv.append(",");
}
csv.append(key);
// store list
list.add(tmp);
notFirst = false;
}
csv.append("\n");
// Write the rest of the rows
while(row<numberOfTotalRow) {
notFirst = true;
for(int x=0;x<list.size();x++) {
if(!notFirst) {
csv.append(",");
}
csv.append((String)list.get(x).get(row));
notFirst = false;
}
row++;
}
You can make a method that prints out the map as you wish:
public void toString(HashMap<String, ArrayList<String>> map) {
for(int i = 0; i < map.size(); i++) {
ArrayList<String> list = new ArrayList<String>(map.keySet());
String key = list.get(i);
System.out.println(key);
for(int j = 0; j < map.get(key).size(); j++)
System.out.println(map.get(key).get(j));
}
}
The way you have imagined is impossible. A file is a continuous stream of bytes. So after you write the first value, you have this in your file : "value1\none\nthree\nfive". If you then seek to position 6 (after "value") and insert new characters, you'll be overwiting the first value's second row. The following bytes won't be magically pushed away.
The only way to do this is to traverse the data you have in a way that allows you to output the bytes in the same order that they will be in the file. So: go to each value and write the first element, to each value again and write their second element and so on.
You don't need a RandomAccessFile file, better use this:
HashMap<String, ArrayList<String>> map = new HashMap<>();
map.put("a", new ArrayList<>(Arrays.asList(new String[]{"A1", "A2", "A3"})));
map.put("b", new ArrayList<>(Arrays.asList(new String[]{"B1", "B2", "B3"})));
map.put("c", new ArrayList<>(Arrays.asList(new String[]{"C1", "C2", "C3"})));
{
/**
* Set your file printstream. For testing System.out
*/
PrintStream ps = System.out;
boolean first = true;
/**
* Size of the array list. Let's asume that the arraylist are of the
* same lenght;
*/
int s = 0;
/**
* Create a ArrayList variable because, this map class makes no guarantees
* as to the order of the map; in particular, it does not guarantee that
* the order will remain constant over time.
*/
ArrayList<Entry<String, ArrayList<String>>> l =
new ArrayList<>(map.entrySet());
for (Entry<String, ArrayList<String>> e : l) {
if (first) {
first = false;
s = e.getValue().size();
} else {
ps.print(",");
}
ps.print(e.getKey());
}
ps.println();
for (int i = 0; i < s; i++) {
first = true;
for (Entry<String, ArrayList<String>> e : l) {
if (first) {
first = false;
} else {
ps.print(",");
}
ps.print(
e.getValue().get(i));
}
ps.println();
}
}
Output:
b,c,a
B1,C1,A1
B2,C2,A2
B3,C3,A3

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.

Efficient way to delete values from hashmap object

I have HashMap object contains a key x-y-z with corresponding value test-test1-test2.
Map<String,String> map = new HashMap<String,String>();
map.put("x-y-z","test-test1-test2");
map.put("x1-y1-z1","test-test2-test3");
Now I have an input string array that contains some piece of the key:
String[] rem={"x","x1"}
Based on this string array I want to remove HashMap values.
Can anyone give an efficient approach to do this operation?
List remList = Arrays.asList(rem);
for (Iterator it = map.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
String[] tokens = key.split("-");
for (int i = 0; i < tokens.length; i++) {
String token = tokens[i];
if (remList.contains(token)) {
it.remove();
break;
}
}
}
And an updated version with adding functionality based on your latest comment on this answer:
private static Map getMapWithDeletions(Map map, String[] rem) {
Map pairs = new HashMap();
for (int i = 0; i < rem.length; i++) {
String keyValue = rem[i];
String[] pair = keyValue.split("#", 2);
if (pair.length == 2) {
pairs.put(pair[0], pair[1]);
}
}
Set remList = pairs.keySet();
for (Iterator it = map.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
String[] tokens = key.split("-");
for (int i = 0; i < tokens.length; i++) {
String token = tokens[i];
if (remList.contains(token)) {
it.remove();
pairs.remove(token);
break;
}
}
}
map.putAll(pairs);
return map;
}
Edited based on edited question.
Loop through the keySet of the hashmap. When you find a key that starts with x you are looking for remove it from the map.
Something like:
for(String[] key: map.keySet()){
if(key.length>0 && x.equals(key[0])){
map.remove(key);
}
}
Assuming I understand you correctly, and you want to remove everything starting with 'x-' and 'x1-' from the map (but not 'x1111-', even though 'x1' is a prefix of 'x1111'), and efficiency is important, you might want to look at one of the implementations of NavigableMap, such as (for example) TreeMap.
NavigableMaps keep their entries in order (by natural key order, by default), and can be iterated over and searched very efficiently.
They also provide methods like subMap, which can produce another Map which contains those keys in a specified range. Importantly, this returned Map is a live view, which means operations on this map affect the original map too.
So:
NavigableMap<String,String> map = new TreeMap<String,String>();
// populate data
for (String prefixToDelete : rem) {
// e.g. prefixToDelete = "x"
String startOfRange = prefixToDelete + "-"; // e.g. x-
String endOfRange = prefixToDelete + "`"; // e.g. x`; ` comes after - in sort order
map.subMap(startOfRange, endOfRange).clear(); // MAGIC!
}
Assuming your map is large, .subMap() should be much faster than iterating over each Map entry (as a TreeMap uses a red-black tree for fast searching).
You can do the following:
Map<String,String> map = new HashMap<String,String>();
map.put("x-y-z","test-test1-test2");
map.put("x1-y1-z1","test-test2-test3");
String[] rem={"x","x1"};
for (String s : rem) {
map.keySet().removeIf(key -> key.contains(s));
}
This piece of code will remove all entries with "x" or "x1" in the map key.

Categories

Resources