Converting a awk 2D array with counts into hashmap in java - java

I found this problem so interesting. I am using an awk 2D array that has a key,value,count of the same. and that is being printed to a file. This file is in the below format
A100|B100|3
A100|C100|2
A100|B100|5
Now I have a file like this .. My motive is to convert this file into a hash map so that the final output from the hash map is.
A100|B100|8
A100|C100|2
Just an aggregation
The challenge is, this one has 3 dimensions and not two. I did have an another file in the below format which is
D100|4
H100|5
D100|6
I easily aggregated the above as it is only 2D and I used the below code to do that
String[] fields= strLine.trim().split("\\|");
if(hashmap.containsKey(fields[0]))
{
//Update the value of the key here
hashmap.put(fields[0],hashmap.get(fields[0]) + Integer.parseInt(fields[1]));
}
else
{
//Inserting the key to the map
hashmap.put(fields[0],Integer.parseInt(fields[1]));
}
So this was quite simple for implementation.
But when it comes to 3D I have to have an another check inside.. My idea for this is to maintain a [B100,5(beanObject[5])]
Map<String,beanClassObject> hashmap=new Map<String,beanClassObject>();
secongField hash map which has been used in the code that has a mapping relation between the created ben Object subscript and the key as the second field "For instance it is "
This bean class would have the getter and setter method for the 2nd and 3rd fields of the file. I hope I am clear with this point. So the implementation of this would be
if(hashmap.containsKey(fields[0]))
{
**//Have to check whether the the particular key value pair already exists ... I dint find any method for this ... Just a normal iteration is there .. Could you ppl guide me regarding this**
//Update the value of the key here
secondFieldHashMap.get(fields[1]).COunt= secondFieldHashMap.get(fields[1]).getCOunt+ Integer.parseInt(fields[2]));
}
else
{
//Inserting the key to the map
hashmap.put(fields[0],Integer.parseInt(fields[1]));
secondFieldHashMap.get(fields[1]).COunt= Integer.parseInt(fields[2]));
}
else
{
// This meands there is no key field
// Hence insert the key field and also update the count of seconfFieldHashMap as done previously.
}
COuld you ppl please throw some ideas regarding this. Thank you

Consider using a Table available in the Google Guava libraries.

Related

How to add new key to map in Firestore

I want to add new key to a map. memberFees is a field of a document under collection named Faculty
I want to store only the key of each member fee inside the memberFees map.
Here is an example of my memberFees map:
I only added that keys in the example manually.
This is what I did:
writeBatches.get(batchIndex).update(db.collection("Faculty")
.document(faculty.getId()), "memberFees/" + memberFeeId, true);
This code throws an error:
java.lang.IllegalArgumentException: Invalid document reference. Document references must have an even number of segments, but Faculty/7DEj7mlTPBf3cVSCtQO3/memberFees has 3
at com.google.firebase.firestore.DocumentReference.forPath(DocumentReference.java:81)
When updating a nested field, use . to separate the field names. Your code uses /, which Firestore interprets as a subcollection.
So:
writeBatches.get(batchIndex).update(db.collection("Faculty")
.document(faculty.getId()), "memberFees." + memberFeeId, true)
// 👆

SnakeYAML load into Guava MultiMap

I am trying to load a Yaml file into a MultiMap using SnakeYAML, but I keep encountering the following exception: java.base/java.util.LinkedHashMap cannot be cast to com.google.common.collect.Multimap. Is there any way to efficiently and effectively load a SnakeYAML object into a Guava MultiMap? I am aware that you can do this with regular HashMaps, but my target Yaml has duplicate keys, so it requires the use of MultiMaps. Thanks for the help in advance. My code for populating the MultiMap using SnakeYAML is as follows:
//Read the config file
InputStream configIn;
try {
configIn = FileUtil.loadFileAsStream(configPath);
//Load the config file into the YAML object
pluginConf = LinkedHashMultimap.create((Multimap<String, Object>) configData.load(configIn));
}
catch(FileNotFoundException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
EDIT: Sample YAML that has duplicate keys
join:
message: "JMessage1"
quit:
message: "QMessage1"
join:
message: "JMessage2"
quit:
message: "QMessage2"
join:
message: "JMessage3"
quit:
message: "QMessage3"
I did manage to solve this problem, but I used regex with regular HashMaps instead of the Guava Multimaps like I originally intended. For example, here's a YAML file that has duplicated keys:
join:
message: "JMessage1"
quit:
message: "QMessage1"
join:
message: "JMessage2"
quit:
message: "QMessage2"
To parse out all of the messages, all I did was simply add numbers to each of the parent keys that were being repeated (join becomes join1, quit becomes quit1, and so on). Since each key has a number in it, they can easily be reverted back to just saying join or quit with the following regex: str.replaceAll("[^a-zA-Z.]", "").toLowerCase() in a for loop that iterates through the HashMap. Since the HashMap entries now just read as join, quit, join, quit when put through the loop, their values can be easily grabbed using something like the following snippet:
if(entry.equals("join")){
//Do stuff
}
After that, the values can be added to something like an ArrayList or other collection. In my case, I used an ArrayList and assigned the properties of the YAML file to instance variables of an object. The following snippet from one of my classes in the project accomplishes this:
//Iterate through the HashMap
for(Entry<?, ?> configEntry : pluginConf.entrySet()){
//Get a string from the selected key that contains only lower-case letters and periods
String entryKey = configEntry.getKey().toString().replaceAll("[^a-zA-Z.]", "").toLowerCase();
//Search for join messages
if(entryKey.equals("messages.join")){
//Get the key name of the current entry
String joinKeyName = configEntry.getKey().toString();
//Create a join message object
JoinMessage newJoinMessage = new JoinMessage(,
configData.getString(joinKeyName + ".message")
);
//Add the join message object to the join message ArrayList
joinMessages.add(newJoinMessage);
//Add to the join message quantity
joinMsgQuantity ++;
}
}
Not really using HashMaps that allow duplicates like I originally asked for, but this "hack" worked flawlessly for me. Hope this helps anyone else looking to do something like this.

How to sort a csv file?

I want to create a file in this format:
device1,t1,t2,t3,t4,t5
device2,t1,t2,t3,t4,t5
device3,t6,t7,t8,t9,t10
device4,t6,t7,t8,t9,t10
Here, t1, t2, ..., tn are time stamps.
Every value tn is generated based on one execution of JAR file along with that device name gets generated too.
I am able to generate a format like this using the JAR file now:
For example:
Current format in csv file:
device1,t1,device2,t2,device2,t3,device1,t4,device2,t5,device2,t6,device1,t7,device2,t8
I want this in this format in csv file:
device1-t1,t4,t7
device2-t2,t3,t5,t6,t8
So here, I have to put the time stamp belonging to specific devices on the right-hand side.
Please let me know how can I sort it in Java.
I will answer this question here as per my understanding of your question.
What you can do is to create a hashmap which stores device name as hashmap key.
And then for values create a sortedCollection.
Feed your timestamp in this sorted collection and keep updating this HashMap for the corresponding device name key.
As and when you will update your sorted timestamp collections, they will automatically be stored in sorted manner.
your hashmap will look like :
key : value (collection)
device1 : t1, t4, t7
device2 : t2, t5, t8 (add more timestamp in the end of this collection)
Then feed this hashmap data in the CSV file.
This is to do from java end.
If you want to sort in csv whenever a new timestamp is added for a device, then I dont think so that you can do this from java. Then you would have to keep some logic in csv file once all your data is added in csv file.
This is the solution:
I got output as:
Entire map:{Device1=[[t8], t9], Device2=[[[[[t2], t3], t5], t7], t10]}
BufferedReader reader = new BufferedReader(new FileReader("results.csv"));
String eachline;
// int i=2, j=2;
while((eachline = reader.readLine()) != null)
{
String[] fields = eachline.split(",");
if(Integer.parseInt(fields[2])==0)//data is = 0
{
if(tree.get(fields[0])!=null)//returns null if this key not present
{
values.add(tree.get(fields[0]));//get entire key value pair for that particular field
}
values.add(fields[1]);//to prev value, add next value
tree.put(fields[0], values.toString());// write to hashmap along with value
values.clear();
}
}
System.out.println("Entire map:"+tree);

java: convert HashMap with dynamic keys to Bean

I'm trying to convert a large Map> to some JavaBean. The key of map corresponds to some property of JavaBean, and the value somehow is decoded to property value. So I decided to use some util for that, but don't know what will work. There are some requirements I have to this util (or framework):
all configuration must be in separate files
should be a possibility to map dynamic quantity of keys:
there is a map:
key | value
quan | n
key_1| value_1
key_2| value_2
........ | .............
key_n| value_n
where n - is any number
and the JavaBean has a List of some beans. They have a property. value_1, value_2, ... must be mapped in this property, and in the end there must be so much beans in list, as these keys and values in map.
3.. should be a possibility to set up custom decoder for property mapping, because in most cases the value in map is a List with 1 value, so I need to get the first item of list (if it's not empty).
4.. should be a possibility run some script to execute extraordinary mappings, for example:
there is a map, that is described in 2d point.
and the JavaBean has a property of type HashMap, where value_1 is mapped to Bean1 and some analogous value from input map is mapped to Bean2.
I've tried to use smooks, but when I've started, all these requirements were not clear yet and the smooks was something new, I haven't worked with it until now. So the smooks config doesn't contain the whole business-logic (because of second req.) and looks ugly, I don't like that. I can show the most ugliest fragment for 2d point:
<jb:bean beanId="javaBean" class="com.example.JavaBean" createOnElement="map">
<jb:wiring property="someBeans" beanIdRef="someBeanItems"/>
</jb:bean>
<jb:bean beanId="someBeanItems" class="java.util.ArrayList" createOnElement="map/entry">
<jb:wiring beanIdRef="someBeanItem"/>
</jb:bean>
<jb:bean beanId="someBeanItem" class="com.example.someBeanItem" createOnElement="map/entry">
<condition>map.quan[0]>0</condition>
<jb:expression property="property1">
index = map.quan[0]-1;
value = additionalProperties.property1_List[index];
map.quan[0] = map.quan[0] - 1;
return value;
</jb:expression>
</jb:bean>
Here "property1_List" is builded before executing smooks.
Now I look for something more nice and need your help: maybe you know how to make that better using smooks? Or what another frameworks for mapping can you recommend for my issue?

retrieving the values from the nested hashmap

I have a XML file with many copies of table node structure as below:
<databasetable TblID=”123” TblName=”Department1_mailbox”>
<SelectColumns>
<Slno>dept1_slno</Slno>
<To>dept1_to</To>
<From>dept1_from</From>
<Subject>dept1_sub</Subject>
<Body>dept1_body</Body>
<BCC>dept1_BCC</BCC>
<CC>dept1_CC</CC>
</SelectColumns>
<WhereCondition>MailSentStatus=’New’</WhereCondition>
<UpdateSuccess>
<MailSentStatus>’Yes’</MailSentStatus>
<MailSentFailedReason>’Mail Sent Successfully’</MailSentFailedReason>
</UpdateSuccess>
<UpdateFailure>
<MailSentStatus>’No’</MailSentStatus>
<MailSentFailedReason>’Mail Sending Failed ’</MailSentFailedReason>
</ UpdateFailure>
</databasetable>
As it is not an efficient manner to traverse the file for each time to fetch the details of each node for the queries in the program, I used the nested hashmap concept to store the details while traversing the XML file for the first time. The structure I used is as below:
MapMaster
Key Value
123 MapDetails
Key Value
TblName Department1_mailbox
SelectColumns mapSelect
Key Value
Slno dept1_slno
To dept1_to
From dept1_from
Subject dept1_sub
Body dept1_body
BCC dept1_BCC
CC dept1_CC
WhereCondition MailSentStatus=’New’
UpdateSuccess mapUS
MailSentStatus ’Yes’
MailSentFailedReason ’Mail Sent Successfully’
UpdateFailure mapUF
MailSentStatus ’No’
MailSentFailedReason ’Mail Sending Failed’
But the problem I’m facing now is regarding retrieving the Value part using the nested Keys. For example,
If I need the value of Slno Key, I have to specify TblID, SelectColumns, Slno in nested form like:
Stirng Slno = ((HashMap)((HashMap)mapMaster.get(“123”))mapDetails.get(“SelectColumns”))mapSelect.get(“Slno”);
This is unconvinent to use in a program. Please suggest a solution but don’t tell that iterators are available. As I’ve to fetch the individual value from the map according to the need of my program.
EDIT:my program has to fetch the IDs of the department for which there is privilege to send mails and then these IDs are compared with the IDs in XML file. Only information of those IDs are fetched from XML which returned true in comparison. This is all my program. Please help.
Thanks in advance,
Vishu
Never cast to specific Map implementation. Better use casting to Map interface, i.e.
((Map)one.get("foo")).get("bar")
Do not use casting in your case. You can define collection using generics, so compiler will do work for you:
Map<String, Map> one = new HashMap<String, Map>();
Map<String, Integer> two = new HashMap<String, Integer>();
Now your can say:
int n = one.get("foo").get("bar");
No casting, no problems.
But the better solution is not to use nested tables at all. Create your custom classes like SelectColumns, WhereCondition etc. Each class should have appropriate private fields, getters and setters. Now parse your XML creating instance of these classes. And then use getters to traverse the data structure.
BTW if you wish to use JAXB you do not have to do almost anything! Something like the following:
Unmarshaller u = JAXBContext.newInstance(SelectColumns.class, WhereCondition.class).createUnmarshaller();
SelectColumns[] columns = (SelectColumns[])u.unmarshal(in);
One approach to take would be to generate fully qualified keys that contain the XML path to the element or attribute. These keys would be unique, stored in a single hashmap and get you to the element quickly.
Your code would simply have to generate a unique textual representation of the path and store and retrieve the xml element based on the key.

Categories