How can I clone contents of Stringbuilder based on number of records and append record to each row of cloned contents. I'm trying to write data to CSV in way each rows have duplicate columns values repeated by times size of records.
Sample Output CSV should look like.
CN1| CN2| CN3
1 b c
1 d f
2 g h
Here's sample Java Code I'm using
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CSVWrite {
public static Map<String, List<Records>> getData() {
Map<String, List<Records>> fields = new HashMap<>();
List<Records> records_1 = new ArrayList<>();
Records sample_1 = new Records();
sample_1.setName("b");
sample_1.setId("c");
Records sample_2 = new Records();
sample_2.setName("d");
sample_2.setId("f");
records_1.add(sample_1);
records_1.add(sample_2);
List<Records> records_2 = new ArrayList<>();
Records sample_3 = new Records();
sample_1.setName("g");
sample_1.setId("h");
records_2.add(sample_3);
fields.put("1", records_1);
fields.put("2", records_2);
return fields;
}
public static void main(String args[]) {
CSVWrite write = new CSVWrite();
String csvString = write.getCsvString();
String expectedString = "1,b,c\n" + "1,d,f\n" + "2,g,h";
System.out.println(csvString.equals(expectedString));
}
public String getCsvString() {
Map<String, List<Records>> fields = CSVWrite.getData();
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, List<Records>> entry : fields.entrySet()) {
sb.append(entry.getKey());
List<Records> records = entry.getValue();
for (int i = 0; i < records.size(); i++) {
// how to clone contents of sb repeated times based on records size and append
// record items to all.
}
}
return sb.toString();
}
}
First, there is an error I think, this code look weird. The var sample_3 is built but not correctly populated:
Records sample_3 = new Records();
sample_1.setName("g");
sample_1.setId("h");
It should be:
Records sample_3 = new Records();
sample_3.setName("g");
sample_3.setId("h");
Finally, there is no need to clone anything to achieve the desired result, simply rewrite getCsvString() like this:
public String getCsvString() {
Map<String, List<Records>> fields = CSVWrite.getData();
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, List<Records>> entry : fields.entrySet()) {
List<Records> records = entry.getValue();
for (Records record : records) {
sb.append(entry.getKey());
sb.append(",").append(record.getName());
sb.append(",").append(record.getId());
sb.append("\n");
}
}
return sb.toString();
}
Those 2 corrections will generate output:
1,b,c
1,d,f
2,g,h
Related
My issue here is I need to compute average time for each Id and compute average time of each id.
Sample data
T1,2020-01-16,11:16pm,start
T2,2020-01-16,11:18pm,start
T1,2020-01-16,11:20pm,end
T2,2020-01-16,11:23pm,end
I have written a code in such a way that I kept first column and third column in a map.. something like
T1, 11:16pm
but I could not able to compute values after keeping those values in a map. Also tried to keep them in string array and split into line by line. By same issue facing for that approach also.
**
public class AverageTimeGenerate {
public static void main(String[] args) throws IOException {
File file = new File("/abc.txt");
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
ArrayList<String> list = new ArrayList<>();
String[] tokens = line.split(",");
for (String s: tokens) {
list.add(s);
}
Map<String, String> map = new HashMap<>();
String[] data = line.split(",");
String ids= data[0];
String dates = data[1];
String transactionTime = data[2];
String transactionStartAndEndTime = data[3];
String[] transactionIds = ids.split("/n");
String[] timeOfEachTransaction = transactionTime.split("/n");
for(String id : transactionIds) {
for(String time : timeOfEachTransaction) {
map.put(id, time);
}
}
}
}
}
}
Can anyone suggest me is it possible to find duplicates in a map and compute values in map, Or is there any other way I can do this so that the output should be like
`T1 2:00
T2 5:00'
I don't know what is your logic to complete the average time but you can save data in map for one particular transaction. The map structure can be like this. Transaction id will be the key and all the time will be in array list.
Map<String,List<String>> map = new HashMap<String,List<String>>();
You can do like this:
Map<String, String> result = Files.lines(Paths.get("abc.txt"))
.map(line -> line.split(","))
.map(arr -> {
try {
return new AbstractMap.SimpleEntry<>(arr[0],
new SimpleDateFormat("HH:mm").parse(arr[2]));
} catch (ParseException e) {
return null;
}
}).collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.collectingAndThen(Collectors
.mapping(Map.Entry::getValue, Collectors.toList()),
list -> toStringTime.apply(convert.apply(list)))));
for simplify I've declared two functions.
Function<List<Date>, Long> convert = list -> (list.get(1).getTime() - list.get(0).getTime()) / 2;
Function<Long, String> toStringTime = l -> l / 60000 + ":" + l % 60000 / 1000;
I have a set of strings like this
A_2007-04, A_2007-09, A_Agent, A_Daily, A_Execute, A_Exec, B_Action, B_HealthCheck
I want output as:
Key = A, Value = [2007-04,2007-09,Agent,Execute,Exec]
Key = B, Value = [Action,HealthCheck]
I'm using HashMap to do this
pckg:{A,B}
count:total no of strings
reports:set of strings
Logic I used is nested loop:
for (String l : reports[i]) {
for (String r : pckg) {
String[] g = l.split("_");
if (g[0].equalsIgnoreCase(r)) {
report.add(g[1]);
dirFiles.put(g[0], report);
} else {
break;
}
}
}
I'm getting output as
Key = A, Value = [2007-04,2007-09,Agent,Execute,Exec]
How to get second key?
Can someone suggest logic for this?
Assuming that you use Java 8, it can be done using computeIfAbsent to initialize the List of values when it is a new key as next:
List<String> tokens = Arrays.asList(
"A_2007-04", "A_2007-09", "A_Agent", "A_Daily", "A_Execute",
"A_Exec", "P_Action", "P_HealthCheck"
);
Map<String, List<String>> map = new HashMap<>();
for (String token : tokens) {
String[] g = token.split("_");
map.computeIfAbsent(g[0], key -> new ArrayList<>()).add(g[1]);
}
In terms of raw code this should do what I think you are trying to achieve:
// Create a collection of String any way you like, but for testing
// I've simply split a flat string into an array.
String flatString = "A_2007-04,A_2007-09,A_Agent,A_Daily,A_Execute,A_Exec,"
+ "P_Action,P_HealthCheck";
String[] reports = flatString.split(",");
Map<String, List<String>> mapFromReportKeyToValues = new HashMap<>();
for (String report : reports) {
int underscoreIndex = report.indexOf("_");
String key = report.substring(0, underscoreIndex);
String newValue = report.substring(underscoreIndex + 1);
List<String> existingValues = mapFromReportKeyToValues.get(key);
if (existingValues == null) {
// This key hasn't been seen before, so create a new list
// to contain values which belong under this key.
existingValues = new ArrayList<>();
mapFromReportKeyToValues.put(key, existingValues);
}
existingValues.add(newValue);
}
System.out.println("Generated map:\n" + mapFromReportKeyToValues);
Though I recommend tidying it up and organising it into a method or methods as fits your project code.
Doing this with Map<String, ArrayList<String>> will be another good approach I think:
String reports[] = {"A_2007-04", "A_2007-09", "A_Agent", "A_Daily",
"A_Execute", "A_Exec", "P_Action", "P_HealthCheck"};
Map<String, ArrayList<String>> map = new HashMap<>();
for (String rep : reports) {
String s[] = rep.split("_");
String prefix = s[0], suffix = s[1];
ArrayList<String> list = new ArrayList<>();
if (map.containsKey(prefix)) {
list = map.get(prefix);
}
list.add(suffix);
map.put(prefix, list);
}
// Print
for (Map.Entry<String, ArrayList<String>> entry : map.entrySet()) {
String key = entry.getKey();
ArrayList<String> valueList = entry.getValue();
System.out.println(key + " " + valueList);
}
for (String l : reports[i]) {
String[] g = l.split("_");
for (String r : pckg) {
if (g[0].equalsIgnoreCase(r)) {
report = dirFiles.get(g[0]);
if(report == null){ report = new ArrayList<String>(); } //create new report
report.add(g[1]);
dirFiles.put(g[0], report);
}
}
}
Removed the else part of the if condition. You are using break there which exits the inner loop and you never get to evaluate the keys beyond first key.
Added checking for existing values. As suggested by Orin2005.
Also I have moved the statement String[] g = l.split("_"); outside inner loop so that it doesn't get executed multiple times.
I have a scenario to count number of names which is stored in the LinkedHashMap , and names can be duplicated but i should not count the duplicate name.
Below is Sample code:
LinkedHashMap<Long,MyApplicationDTO> myApps = (LinkedHashMap<Long,MyApplicationDTO>) request.getAttribute("data");
for (Map.Entry app : myApps.entrySet()) {
Long ID = (Long)app.getKey() ;
MyApplicationDTO singleMyApp = (MyApplicationDTO) app.getValue();
LinkedHashMap<Long, MyDTO> myList = singleMyApp.getMyList();
String name = "";
for (Map.Entry details : myList.entrySet()) {
Long id1 = (Long)details.getKey() ;
MyDTO myDetails = (MyDTO) details.getValue();
name = myDetails.getName(); // For first time it stores A
//how to loop so that i can only get the count of names as 3 by avoiding duplicate names from the below shown list.
//A B A B A B C
}
}
On the Screen i have something as below:
Name :
A
B
A
B
A
B
C
I have to print the count of the name as 3(non repeating names)
As you iterate over the entrySet, add all names to a Set<String>. Then output set.size().
The Set will not add duplicates when you add names by set.add(name), so the size of the set will be the count of uniqe names.
LinkedHashMap<Long,MyApplicationDTO> myApps = (LinkedHashMap<Long,MyApplicationDTO>) request.getAttribute("data");
for (Map.Entry app : myApps.entrySet()) {
Long ID = (Long)app.getKey() ;
MyApplicationDTO singleMyApp = (MyApplicationDTO) app.getValue();
LinkedHashMap<Long, MyDTO> myList = singleMyApp.getMyList();
String name = "";
Set<String> uniqueNames = new HashSet<String>();
for (Map.Entry details : myList.entrySet()) {
Long id1 = (Long)details.getKey() ;
MyDTO myDetails = (MyDTO) details.getValue();
name = myDetails.getName(); // For first time it stores A
//how to loop so that i can only get the count of names as 3 by avoiding duplicate names from the below shown list.
//A B A B A B C
uniqueNames.add(name);
}
}
To get size do =
uniqueNames.size();
I'm not sure I'm understanding your question entirely, but if you're just looking to count the occurrences of unique values in the LinkedHashmap you can do something like this `
public static void main(String[] args) {
LinkedHashMap<Long, String> myApps = new LinkedHashMap<Long, String>();
myApps.put(4L, "A");
myApps.put(14L, "B");
myApps.put(44L, "A");
myApps.put(54L, "B");
myApps.put(46L, "A");
myApps.put(543L, "B");
myApps.put(144L, "C");
ArrayList<String> names = new ArrayList<String>();
for (Map.Entry app : myApps.entrySet()) {
if (!(names.contains(app.getValue()))) {
names.add(app.getValue().toString());
}
}
System.out.println(names.size());
for (String s : names ) {
System.out.print(s + " ");
}
}
One liner with JAVA 8 Stream API
LinkedHashMap<Long, MyDTO> myList = singleMyApp.getMyList();
long disctinctNamesCount = myList.values().stream().map(MyDTO::getNAme).distinct().count();
I have a nested HashMap (outer_map), which has another HashMap inside of it as a value (inner_map), such implemented as
Map<String, HashMap<String, String>> outer_map = new HashMap<String, HashMap<String, String>>();
Map<String, String> inner_map = new HashMap<String, String>();
The figure below illustrates the whole structures of the maps:
To make the long story short, I need to compare and search values inside the outer_map's vlaue (inner_map) by String Array items, and then produce another String Array to add matched items.
If the String Array has there elements which are the same as one of the inner_map's random (for example; value2, value1, and value7) values, how can I search and compare these items to add to another String Array?
The latest code snippet I tried and I couldn't succeed:
if( !( theStringArray.equals("") ) )
{
while( outer_map.keySet().iterator().hasNext() )
{
for( int i=0; i <= theStringArray.length; i++)
{
// outer_map keys are order as 1,2,3,..,8
theStringArray[i] = outer_map.get(String.valueOf(i+1)).get("key1");
...
}
}
}
EDIT: Map generating function
private void parse(String in) throws IOException
{
reader = new JsonReader(new StringReader(in));
...
int nodeCounter = 1;
while(reader.hasNext())
{
...
String nameAsKey1 = "blabla"; // value1
inner_map.put("name", nameAsKey1);
String surnameAsKey2 = "blabla"; // value2
inner_map.put("surname", surnameAsKey2);
...
outer_map.put(String.valueOf(nodeCounter), (HashMap<String, String>) inner_map);
inner_map = new HashMap<String, String>();
nodeCounter++;
}
}
EDIT: I don't know how I can explain the issue more clearly, but may be this will help to understand about it: Map structure
I assume you have an array of String and a Map of map. Now you want to search the value fields of inner map against the array of String and if make a new string array with matching values.
If that is the case the below program will help you..
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class InnerMapSearch {
public static void main(String[] args) {
Map<String, HashMap<String, String>> outer_map = new HashMap<String, HashMap<String, String>>();
Map<String, String> inner_map = new HashMap<String, String>();
String[] searchParams = {"blabla1", "blabla3", "blabla20"};
//Populating the map
int reader = 1;
while (reader < 10) {
String nameAsKey1 = "blabla" + reader; // value1
inner_map.put("name", nameAsKey1);
String surnameAsKey2 = "blabla" + reader; // value2
inner_map.put("surname", surnameAsKey2);
outer_map.put(String.valueOf(reader), (HashMap<String, String>) inner_map);
inner_map = new HashMap<String, String>();
reader++;
}
//Searching
Set<String> searchResults = new HashSet<String>(); // Using set to avoid duplicate
// Iterate over the outer map
for(String key : outer_map.keySet()){
// Iterate through each inner_map value of outer map
for(Entry<String, String> innerEntry : outer_map.get(key).entrySet()){
// Iterate through the list of search params and see if its present in inner_hashmap
for(String searchParam : searchParams){
if(searchParam.equals(innerEntry.getValue())){
// The search parameter is in inner map so adding to result.
searchResults.add(searchParam);
}
}
}
}
// Converting the list to an array.
String[] searchResultsArray = searchResults.toArray(new String[searchResults.size()]);
}
}
String format is (not json format):
a="0PN5J17HBGZHT7JJ3X82", b="frJIUN8DYpKDtOLCwo/yzg="
I want convert this string to a HashMap:
key a with value 0PN5J17HBGZHT7JJ3X82
key b with value frJIUN8DYpKDtOLCwo/yzg=
Is there a convenient way? Thanks
What I've tried:
Map<String, String> map = new HashMap<String, String>();
String s = "a=\"00PN5J17HBGZHT7JJ3X82\",b=\"frJIUN8DYpKDtOLCwo/yzg=\"";
String []tmp = StringUtils.split(s,',');
for (String v : tmp) {
String[] t = StringUtils.split(v,'=');
map.put(t[0], t[1]);
}
I get this result:
key a with value "0PN5J17HBGZHT7JJ3X82"
key b with value "frJIUN8DYpKDtOLCwo/yzg
for key a, the start and end double quotation marks(") is unwanted; for key b, the start double quotation marks(") is unwanted and the last equals sign(=) is missing.
Sorry for my poor english.
Probably you don't care that it's a HashMap, just a Map, so this will do it, since Properties implements Map:
import java.io.StringReader;
import java.util.*;
public class Strings {
public static void main(String[] args) throws Exception {
String input = "a=\"0PN5J17HBGZHT7JJ3X82\", b=\"frJIUN8DYpKDtOLCwo/yzg=\"";
String propertiesFormat = input.replaceAll(",", "\n");
Properties properties = new Properties();
properties.load(new StringReader(propertiesFormat));
System.out.println(properties);
}
}
Output:
{b="frJIUN8DYpKDtOLCwo/yzg=", a="0PN5J17HBGZHT7JJ3X82"}
If you absolutely need a HashMap, you can construct one with the Properties object as input: new HashMap(properties).
Added few changes in Ryan's code
public static void main(String[] args) throws Exception {
String input = "a=\"0PN5J17HBGZHT7JJ3X82\", b=\"frJIUN8DYpKDtOLCwo/yzg=\"";
input=input.replaceAll("\"", "");
String propertiesFormat = input.replaceAll(",", "\n");
Properties properties = new Properties();
properties.load(new StringReader(propertiesFormat));
Set<Entry<Object, Object>> entrySet = properties.entrySet();
HashMap<String,String > map = new HashMap<String, String>();
for (Iterator<Entry<Object, Object>> it = entrySet.iterator(); it.hasNext();) {
Entry<Object,Object> entry = it.next();
map.put((String)entry.getKey(), (String)entry.getValue());
}
System.out.println(map);
}
Split the String on the Basis of commas (",") and then with with ("=")
String s = "Comma Separated String";
HashMap<String, String> map = new HashMap<String, String>();
String[] arr = s.split(",");
String[] arStr = arr.split("=");
map.put(arr[0], arr[1]);
You can also use the regex as below.
Map<String,String> data = new HashMap<String,String>();
Pattern p = Pattern.compile("[\\{\\}\\=\\, ]++");
String[] split = p.split(text);
for ( int i=0; i+2 <= split.length; i+=2 ){
data.put( split[i], split[i+1] );
}
return data;