Trying to print data to a gui made by javafx.
...
for(Entry<Date, String> entry : tmap.entrySet()) {
Date key = entry.getKey();
String value = entry.getValue();
System.out.println(key + " => " + value);
I do not want to use setText() as it wont act like in console, it will clear to only one text every loop of TreeMap
The only way to do this is by concatenating the original text with the new content and setting the resulting String using setText.
In your case you can improve the efficiency of doing this by using a StringBuilder:
StringBuilder sb = new StringBuilder(textNode.getText());
for(Entry<Date, String> entry : tmap.entrySet()) {
Date key = entry.getKey();
String value = entry.getValue();
sb.append(key).append(" => ").append(value).append('\n');
...
}
textNode.setText(sb.toString());
In case you're using a TextInputControl, appendText may be worth a look, but in case you know you're adding multiple Strings, StringBuilder is probably more efficient.
for(Entry<Date, String> entry : tmap.entrySet()) {
Date key = entry.getKey();
String value = entry.getValue();
textNode.appendText(key + " => " + value + '\n');
...
}
Related
I'm a writing a parser that will extract the tag and value out of a line that it reads from a file and I want to know how to get the value. So in this case I want to get
key = "accountName" and
value = "fname LName" and have it repeat with each line.
<accountName>fname LName</accountName>
<accountNumber>12345678912</accountNumber>
<accountOpenedDate>20200218</accountOpenedDate>
This is my code, this is within a while loop that is scanning each line using bufferedReader. I managed to get the key properly, but when I try to get the value, I get "String index out of range - 12. Not sure how to get the value between the two arrows > <.
String line;
if(line.startsWith("<"){
key = line.substring(line.indexOf("<"+1, line.indexOf(">"));
value = line.substring(line.indexOf(">"+1, line.indexOf("<")+1);
}
Though it is recommended to use XML parser but still if you want to do it by manually processing the string at each line:
(using regular expression is recommended to process line) but if you want todo manually with substring way here is the example:
private static void readKeyValue(String line) {
String key = null;
String value = null;
if (null != line && line.startsWith("<") && line.contains("</")) {
key = line.substring(line.indexOf("</")+ 2 , line.lastIndexOf(">"));
value = line.substring(line.indexOf(">") + 1, line.indexOf("</"));
}
System.out.println("key: "+ key);
System.out.println("value: "+ value);
}
You can use regular expressions to extract, assuming the line variable is a string read from each line.
String pattern = "<([a-zA-Z]+.*?)>([\\s\\S]*?)</[a-zA-Z]*?>";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Now create matcher object.
Matcher m = r.matcher(line);
// find
if (m.find()) {
String key = m.group(1);
String value = m.group(2);
System.out.println("Key: " + key);
System.out.println("Value: " + value);
} else {
System.out.println("Invalid");
}
I have the next map values:
{title=varchar(50), text=text}
I am trying to convert it into two strings like this:
StringBuffer string = new StringBuffer();
for (String keyinside: values.keySet()) {
string.append(keyinside + " " + values.get(keyinside) + ", ");
}
But what I want here - not inlude ", " at the last iteration. How can I do it?
Short java 8 alternative:
String result = values.entrySet().stream().map(e -> e.getKey() + " " + e.getValue())
.collect(Collectors.joining(", "))
Stream.map() to convert all entries in the map to a string description of the entry.
Note that Java 8 also finally adds the function String.join().
Use some indicator :
StringBuffer string = new StringBuffer();
boolean first = true;
for (String keyinside: values.keySet()) {
if (!first)
string.append (", ");
else
first = false;
string.append(keyinside + " " + values.get(keyinside));
}
BTW, it's more efficient to use StringBuilder (assuming you don't need thread safety).
I quite like Joiner from Google collections library. You could just do this:
on(",").withKeyValueSeparator(" ").join(values);
on is statically imported from com.google.common.base.Joiner.
If you use Maven, just add a dependency:
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0</version>
</dependency>
Take a counter which increments in every iteration and get a if condition which checks whether it is iterating the last time
A simple trick is
int i = 0 ;
for (String keyinside: values.keySet()) {
string.append(keyinside + " " + values.get(keyinside));
if((i+1)<values.keySet().size()){
string.append(", ");
}
i++;
}
Also I suggest you to use StringBuilder if thread safety is not a concern
You can try this .by which we can remove the comma(,) at end.
Hope this helps you.
Map<String,String> s= new LinkedHashMap<String,String>();
s.put("1", "A");
s.put("2", "B");
s.put("3", "C");
StringBuffer sb = new StringBuffer();
String ans=null;
for (String keyinside: s.keySet()) {
sb.append(keyinside + " " + s.get(keyinside) + ", ").toString();
}
System.out.println(sb);
ans=sb.substring(0, sb.length()-2).toString();
System.out.println(ans);
Note: you can refer How to remove the last character from a string?
I've searched stacked overflow and the net and I found similar questions but none that gave me a concrete answer. I have a string that acts as a list with the following formatting
Key(Value)/Key(value)/Key(value,value)). I would like to match them by key name IF the key exists, so I don't really want the parenthesis included anywhere.. just the key and the value. I coded something out, but it's a real mess...
so my conditions are:
1)extract key value pairs without parenthesis
2)extract IF they are available...
3)If value portion of list contains two values delimited by a ",", extract individually
textToParse = "TdkRoot(0x0)/Tdk(0x2,0x0)/Tdk(0x0,0x1)/VAL(40A8F0B32240,2x4)/SN(0000:0000:0000:0000:0000:0000:0000:0000/IP(000.1.000.1)/Blue(2x4,2x4)"
String patternText = "^TdkRoot\(( [A-Za-z0-9]) Tdk\(( \\w}+) VAL\(( \\w) SN\(( \\w) IP\ (( \\w) Blue\(( \\w)"
Pattern pattern = Pattern.compile( patternText );
Matcher matcher = pattern.matcher(textToParse);
//Extract the groups from the regex (e.g. elements in braces)
String messageId = matcher.group( 1 );
String submitDate = matcher.group(4);
String statusText = matcher.group( 6 );
I think a cleaner/easier approach would be to extract the elements using patterns for each individual key/value. If so what pattern could I use to tell regex: for "key" grab "value" but leave the parenthesis... if value is delimited by a coma.. return array?? possibly?
Thanks Community!! Hope to hear from you!
PS I know (?<=\()(.*?)(?=\)) will capture anything in the parentheses "(This) value was captured), but how can I modify that to specify a key before the parentheses? "I want to capture whats in THIS(parentheses)" ... key THIS
possibly delimited by a coma
public static void main(String[] args) {
String textToParse = "TdkRoot(0x0)/Tdk(0x2,0x0)/Tdk(0x0,0x1)/VAL(40A8F0B32240,2x4)/SN(0000:0000:0000:0000:0000:0000:0000:0000)/IP(000.1.000.1)/Blue(2x4,2x4)";
Pattern p = Pattern.compile("(\\w+)\\((.*?)\\)");
Matcher m = p.matcher(textToParse);
while (m.find()) {
System.out.println("key :" + m.group(1));
if (m.group(2).contains(",")) {
String[] s = m.group(2).split(",");
System.out.println("values : " + Arrays.toString(s));
} else {
System.out.println("value :" + m.group(2));
}
}
}
o/p:
key :TdkRoot
value :0x0
key :Tdk
values : [0x2, 0x0]
key :Tdk
values : [0x0, 0x1]
key :VAL
values : [40A8F0B32240, 2x4]
key :SN
value :0000:0000:0000:0000:0000:0000:0000:0000
key :IP
value :000.1.000.1
key :Blue
values : [2x4, 2x4]
Not sure if this is what you are looking for (your sample code does not compile) but the following code parses the input text into a map :
String inputText = "TdkRoot(0x0)/Tdk(0x2,0x0)/Tdk(0x0,0x1)/VAL(40A8F0B32240,2x4)/SN(0000:0000:0000:0000:0000:0000:0000:0000)/IP(000.1.000.1)/Blue(2x4,2x4)";
Pattern outerPattern = Pattern.compile("([^/()]+)\\(([^()]+)\\)");
Pattern innerPattern = Pattern.compile("([^,]+)");
Map<String, Collection<String>> parsedData = new HashMap<String, Collection<String>>();
Matcher outerMatcher = outerPattern.matcher(inputText);
while (outerMatcher.find()) {
String key = outerMatcher.group(1);
String val = outerMatcher.group(2);
Collection<String> valueCollection = new ArrayList<String>();
Matcher innerMatcher = innerPattern.matcher(val);
while (innerMatcher.find()) {
valueCollection.add(innerMatcher.group(1));
}
parsedData.put(key, valueCollection);
}
System.out.println(parsedData);
The resulting map (printed on last line) is
{Blue=[2x4, 2x4], VAL=[40A8F0B32240, 2x4], IP=[000.1.000.1], TdkRoot=[0x0], SN=[0000:0000:0000:0000:0000:0000:0000:0000], Tdk=[0x0, 0x1]}
I've a tricky condition which does not seem to work. For a given string, "Hi [HandleKey], you have [Action]", and a map which contains, map<"HandleKey","Peter"> I want to replace the square bracket and the word within if the key is found in the map. In this case, the map does not contain the key Action. The string should return "Hi Peter, you have [Action]".
Here is the code that I'm working on:
private String messageFormatter(String tMessage, Map<String, String> messageMap)
{
String formattedMsg = null;
Set<String> keyset = messageMap.keySet();
Iterator<String> keySetItr = keyset.iterator();
String msgkey = null;
boolean isFormatted = false;
while (keySetItr.hasNext())
{
msgkey = keySetItr.next();
if(t.contains(msgkey))
{
if(!isFormatted)
{
formattedMsg = tMessage.replaceAll("\\[", "").replaceAll("\\]", "");
formattedMsg = formattedMsg.replaceAll(msgkey, messageMap.get(msgkey));
isFormatted= true;
}else
{
formattedMsg = formattedMsg.replaceAll(msgkey, messageMap.get(msgkey));;
}
}else
{
formattedMsg=tMessage;
}
}
return formattedMsg;
}
The last else part is not right. Can anyone please help me with this. This code works fine for all the cases except when a matching key is not found in the map
is this idea ok for you?
instead of applying regex or extracting the stuff between [..], you could do some trick on your map side. e.g.
String s = "Hi [HandleKey], you have [Action]";
for(String k: yourMap.keySet()){
s=s.replaceAll("\\["+k+"\\]",yourMap.get(k));
}
You can do this with regex, here is a complete example code
public static void main(String[] args) {
String str = "Hi [HandleKey], you have [Action] ";
Hashtable<String, String> table = new Hashtable<String, String>();
table.put("HandleKey", "Peter");
Pattern pattern = Pattern.compile("\\[(\\w+)\\]");
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
String key = matcher.group(1);
if (table.containsKey(key)) {
str = str.replaceFirst("\\[" + key + "\\]", table.get(key));
}
}
System.out.println(str);
}
Output:
Hi Peter, you have [Action]
Note that this is more efficient than looping over the Map if the map size is already large or growing.
To handle when key not in map with minimal changes to what you have above try
formattedMsg.replaceAll(msgkey,
(messageMap.containsKey(msgKey) ? messageMap.get(msgkey) : "[" + msgKey + "]"));
but looking again I can see that you're iterating the set of keys from the messageMap so the issue of a key not appearing in the map doesn't arise?
There's also a reference to if(t.contains(msgKey))... but not sure what t is
if you want the text to contain the formatted [msgKey] when its no found then replacing all "[" & "]" seems the wrong way to start if you want to put them back in in some cases.
I'd look at #iTech's suggestion and get regex doing more for you
I have a text file with Tag - Value format data. I want to parse this file to form a Trie. What will be the best approach?
Sample of File: (String inside "" is a tag and '#' is used to comment the line.)
#Hi, this is a sample file.
"abcd" = 12;
"abcde" = 16;
"http" = 32;
"sip" = 21;
This is basically a properties file, I would remove the " around the tags, then use the Properties class http://java.sun.com/javase/6/docs/api/java/util/Properties.html#load(java.io.Reader) to load the file.
Read that in using Properties and trim the excess parts (", ; and whitespace). Short example:
Properties props = Properties.load(this.getClass()
.getResourceAsStream("path/to.file"));
Map<String, String> cleanedProps = new HashMap<String, String>();
for(Entry pair : props.entrySet()) {
cleanedProps.put(cleanKey(pair.getKey()),
cleanValue(pair.getValue()));
}
Note that in the solution above you only need implement the cleanKey() and cleanValue() yourself. You may want to change the datatypes accordingly if necessary, I used Strings just as an example.
There are many ways to do this; others have mentioned that java.util.Properties gets most of the job done, and is probably the most robust solution.
One other option is to use a java.util.Scanner.
Use the Scanner(File) constructor to scan a file
You can useDelimiter appropriate for this format
nextInt() can be used to extract the numbers
Perhaps you can put the key/value pairs into a SortedMap<String,Integer>
Here's an example that scans a String for simplicity:
String text =
"#Hi, this is a sample file.\n" +
"\n" +
"\"abcd\" = 12; \r\n" +
"\"abcde\"=16;\n" +
" # \"ignore\" = 13;\n" +
"\"http\" = 32; # Comment here \r" +
"\"zzz\" = 666; # Out of order! \r" +
" \"sip\" = 21 ;";
System.out.println(text);
System.out.println("----------");
SortedMap<String,Integer> map = new TreeMap<String,Integer>();
Scanner sc = new Scanner(text).useDelimiter("[\"=; ]+");
while (sc.hasNextLine()) {
if (sc.hasNext("[a-z]+")) {
map.put(sc.next(), sc.nextInt());
}
sc.nextLine();
}
System.out.println(map);
This prints (as seen on ideone.com):
#Hi, this is a sample file.
"abcd" = 12;
"abcde"=16;
# "ignore" = 13;
"http" = 32; # Comment here
"zzz" = 666; # Out of order!
"sip" = 21 ;
----------
{abcd=12, abcde=16, http=32, sip=21, zzz=666}
Related questions
Validating input using java.util.Scanner
Iterate Over Map
See also
regular-expressions.info/Tutorial
The most natural way is probably this:
void doParse() {
String text =
"#Hi, this is a sample file.\n"
+ "\"abcd\" = 12;\n"
+ "\"abcde\" = 16;\n"
+ "#More comment\n"
+ "\"http\" = 32;\n"
+ "\"sip\" = 21;";
Matcher matcher = Pattern.compile("\"(.+)\" = ([0-9]+)").matcher(text);
while (matcher.find()) {
String txt = matcher.group(1);
int val = Integer.parseInt(matcher.group(2));
System.out.format("parsed: %s , %d%n", txt, val);
}
}