Variable arguments in java - java

I have the following classes:
public class WhereSqlClause{
public static String build(String pattern, Object... args){
//For instance, pattern = "Some string :placeholder"
//and we call this method as WhereSqlClause.build(pattern, placeholder)
//where placeholder was a local variable initialized before
}
}
My question is how to replace all placeholders like :placeholder with the placeholder.toString() values.
For instance:
String pattern = "Some str another str:place :holder";
Object place = "Place";
Object holder = "Holder";
String WhereSqlClause.build(pattern, place, holder);
//Have to produce "Some str Place another str Holder"
and
String pattern = "Some str :holder another str :place ";
Object place = "Place";
Object holder = "Holder";
String WhereSqlClause.build(pattern, place, holder);
//Have to produce "Some str Holder another str Place"

You can use MessageFormat, which can replace placeholders according to their positions.
You'll need a pattern of the form :
"some template with param {0} and another param {1}"
Then you can write :
public static String build (String pattern, Object... args)
{
MessageFormat formatter = new MessageFormat (pattern);
StringBuffer output = new StringBuffer (256);
return formatter.format (args, output, null).toString();
}

String[] myArgs = {"arg1", "arg2"};
String sentence = "here is a text with :arg and :arg";
int counter = 0;
while (sentence.indexOf(":arg") != -1) {
sentence = sentence.substring(0, sentence.indexOf(":arg")) + myArgs [counter] + sentence.substring(sentence.indexOf(":arg") + 4, sentence.length());
counter++;
}

Example with a single string, after you just have to iterate over args...
//For instance, pattern = "Some string :placeholder"
//and we call this method as WhereSqlClause.build(pattern, placeholder)
//where placeholder was a local variable initialized before
StringBuilder sbPattern = new StringBuilder();
sbPattern.append(pattern);
// you get ":placeholder "
String placeholder = ":"+(String)args[0].toLowerCase() + " ";
// if is in the pattern, replace it
if (pattern.contains(placeholder)) {
int i = pattern.indexOf(placeholder);
sbPattern.replace(i, i + placeholder.length() , (String)args[0] + " ");
}

Related

Multiple string replacements without affecting substituted text in subsequent iterations

I've posted about letters earlier, but this is an another topic, I have a json response that contain 2 objects, from and to , from is what to change, and to is what it will be changed to .
My code is :
// for example, the EnteredText is "ab b test a b" .
EnteredString = EnteredText.getText().toString();
for (int i = 0; i < m_jArry.length(); i++) {
JSONObject jo_inside = m_jArry.getJSONObject(i);
String Original = jo_inside.getString("from");
String To = jo_inside.getString("to");
if(isMethodConvertingIn){
EnteredString = EnteredString.replace(" ","_");
EnteredString = EnteredString.replace(Original,To + " ");
} else {
EnteredString = EnteredString.replace("_"," ");
EnteredString = EnteredString.replace(To + " ", Original);
}
}
LoadingProgress.setVisibility(View.GONE);
SetResultText(EnteredString);
ShowResultCardView();
For example, the json response is :
{
"Response":[
{"from":"a","to":"bhduh"},{"from":"b","to":"eieja"},{"from":"tes","to":"neesj"}
]
}
String.replace() method won't work here, because first it will replace a to bhduh, then b to eieja, BUT here's the problem, it will convert b in bhduh to eieja, which i don't want to.
I want to perfectly convert the letters and "words" in the String according the Json, but that what i'm failing at .
New Code :
if(m_jArry.length() > 0){
HashMap<String, String> m_li;
EnteredString = EnteredText.getText().toString();
Log.i("TestAf_","Before Converting: " + EnteredString);
HashMap<String,String> replacements = new HashMap<String,String>();
for (int i = 0; i < m_jArry.length(); i++) {
JSONObject jo_inside = m_jArry.getJSONObject(i);
String Original = jo_inside.getString("from");
String To = jo_inside.getString("to");
if(isMethodConvertingIn){
//EnteredString = EnteredString.replace(" ","_");
replacements.put(Original,To);
Log.i("TestAf_","From: " + Original + " - To: " + To + " - Loop: " + i);
//EnteredString = EnteredString.replace(" ","_");
//EnteredString = EnteredString.replace(Original,To + " ");
} else {
EnteredString = EnteredString.replace("_"," ");
EnteredString = EnteredString.replace("'" + To + "'", Original);
}
}
Log.i("TestAf_","After Converting: " + replaceTokens(EnteredString,replacements));
// Replace Logic Here
// When Finish, Do :
LoadingProgress.setVisibility(View.GONE);
SetResultText(replaceTokens(EnteredString,replacements));
ShowResultCardView();
Output :
10-10 19:51:19.757 12113-12113/? I/TestAf_: Before Converting: ab a ba
10-10 19:51:19.757 12113-12113/? I/TestAf_: From: a - To: bhduh - Loop: 0
10-10 19:51:19.757 12113-12113/? I/TestAf_: From: b - To: eieja - Loop: 1
10-10 19:51:19.757 12113-12113/? I/TestAf_: From: o - To: neesj - Loop: 2
10-10 19:51:19.758 12113-12113/? I/TestAf_: After Converting: ab a ba
You question would be clearer if you gave the expected output for the function.
Assuming it is: ab b test a b >>>> bhduheieja eieja neesjt bhduh eieja
then see the following, the key point in the Javadoc being "This will not repeat"
http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/StringUtils.html#replaceEach(java.lang.String,%20java.lang.String[],%20java.lang.String[])
Replaces all occurrences of Strings within another String.
A null reference passed to this method is a no-op, or if any "search
string" or "string to replace" is null, that replace will be ignored.
This will not repeat. For repeating replaces, call the overloaded
method.
Example 1
import org.apache.commons.lang3.StringUtils;
public class StringReplacer {
public static void main(String[] args) {
String input = "ab b test a b";
String output = StringUtils.replaceEach(input, new String[] { "a", "b", "tes" },
new String[] { "bhduh", "eieja", "neesj" });
System.out.println(input + " >>>> " + output);
}
}
Example 2
import org.apache.commons.lang3.StringUtils;
public class StringReplacer {
public static void main(String[] args) {
String input = "this is a test string with foo";
String output = StringUtils.replaceEach(input, new String[] { "a", "foo" },
new String[] { "foo", "bar"});
System.out.println(input + " >>>> " + output);
}
}
Try following:
Solution 1:
Traverse the String characters one by one and move the new String to a new StringBuffer or StringBuilder, then call toString() to get the result. This will need you to implement string matching algorithm.
Solution 2 (Using Regex):
For this, you must know the domain of your string. For example, it is [a-zA-Z] then other arbitrary characters (not part of domain) can be used for intermediate step. First replace the actual characters with arbitrary one then arbitrary ones with the target. In example below, [!##] are the arbitrary characters. These can be any random \uxxxx value as well.
String input = "a-b-c";
String output = input.replaceAll("[a]", "!").replaceAll("[b]", "#").replaceAll("[c]", "#");
output = output.replaceAll("[!]", "bcd").replaceAll("[#]", "cde").replaceAll("[#]", "def");
System.out.println("input: " + input);
System.out.println("Expected: bcd-cde-def");
System.out.println("Actual: " + output);
Your issue is quite common. To sum things up :
String test = "this is a test string with foo";
System.out.println(test.replace("a", "foo").replace("foo", "bar"));
Gives : this is bar test string with bar
Expected by you : this is foo test string with bar
You can use StrSubstitutor from Apache Commons Lang
But first you will have to inject placeholders in your string :
String test = "this is a test string with foo";
Map<String, String> valuesMap = new HashMap<>();
valuesMap.put("a", "foo");
valuesMap.put("foo", "bar");
String testWithPlaceholder = test;
// Preparing the placeholders
for (String value : valuesMap.keySet())
{
testWithPlaceholder = testWithPlaceholder.replace(value, "${"+value+"}");
}
And then, use StrSubstitutor
System.out.println(StrSubstitutor.replace(testWithPlaceholder, valuesMap));
It gives : this is foo test string with bar
Here is an method which is strictly just Java. I tried not to use any Java 8 methods here.
public static String translate(final String str, List<String> from, List<String> to, int index) {
StringBuilder components = new StringBuilder();
String token, replace;
int p;
if (index < from.size()) {
token = from.get(index);
replace = to.get(index);
p = 0;
for (int i = str.indexOf(token, p); i != -1; i = str.indexOf(token, p)) {
if (i != p) {
components.append(translate(str.substring(p, i), from, to, index + 1));
}
components.append(replace);
p = i + token.length();
}
return components.append(translate(str.substring(p), from, to, index + 1)).toString();
}
return str;
}
public static String translate(final String str, List<String> from, List<String> to) {
if (null == str) {
return null;
}
return translate(str, from, to, 0);
}
Sample test program
public static void main(String []args) {
String EnteredString = "aa hjkyu batesh a";
List<String> from = new ArrayList<>(Arrays.asList("a", "b", "tes"));
List<String> to = new ArrayList<>(Arrays.asList("bhduh", "eieja", "neesj"));
System.out.println(translate(EnteredString, from, to));
}
Output:
bhduhbhduh hjkyu eiejabhduhneesjh bhduh
Explaination
The algorithm is recursive, and it simply does the following
If a pattern found in the string matches a pattern in the from list
if there is any string before that pattern, apply the algorithm to that string
replace the found pattern with the corresponding pattern in the to list
append the replacement to the new string
discard the pattern in the from list and repeat the algorithm for the rest of the string
Otherwise append the rest of the string to the new string
You could use split like:
String[] pieces = jsonResponse.split("},{");
then you just parse the from and to in each piece and apply them with replace() then put the string back together again. (and please get your capitalization of your variables/methods right - makes it very hard to read the way you have it)
Apache Commons StringUtils::replaceEach does this.
String[] froms = new String[] {"a", "b"};
String[] tos = new String[] {"b","c"};
String result = StringUtils.replaceEach("ab", froms, tos);
// result is "bc"
Why not keep it very simple (if the JSON is always in same format, EG: from the same system). Instead of replacing from with to, replace the entire markup:
replace "from":"*from*" with "from":"*to*"
Why not just change the actual "to" and "from" labels? That way, you don't run into a situation where "bhudh" becomes "eieja". Just do a string replace on "from" and "to".

Java PatternSyntaxException when replacing characters in a String object

I am trying to create string of this list without the following character , [] as will I want to replace all two spaces after deleting them.
I have tried the following but I am geting the error in the title.
Simple:
[06:15, 06:45, 07:16, 07:46]
Result should look as this:
06:15 06:45 07:16 07:46
Code:
List<String> value = entry.getValue();
String timeEntries = value.toString();
String after = timeEntries.replaceAll(",", " ");
String after2 = after.replaceAll(" ", " ");
String after3 = after2.replaceAll("[", "");
String after4 = after3.replaceAll("]", "");
replaceAll replaces all occurrences that match a given regular expression. Since you just want to match a simple string, you should use replace instead:
List<String> value = entry.getValue();
String timeEntries = value.toString();
String after = timeEntries.replace(",", " ");
String after2 = after.replace(" ", " ");
String after3 = after2.replace("[", "");
String after4 = after3.replace("]", "");
To answer the main question, if you use replaceAll, make sure your 1st argument is a valid regular expression. For your example, you can actually reduce it to 2 calls to replaceAll, as 2 of the substitutions are identical.
List<String> value = entry.getValue();
String timeEntries = value.toString();
String after = timeEntries.replaceAll("[, ]", " ");
String after2 = after.replaceAll("\\[|\\]", "");
But, it looks like you're just trying to concatenate all the elements of a String list together. It's much more efficient to construct this string directly, by iterating your list and using StringBuilder:
StringBuilder builder = new StringBuilder();
for (String timeEntry: entry.getValue()) {
builder.append(timeEntry);
}
String after = builder.toString();

How to extract the value of ID1 and ID2 in a string

I have a string test in which I can see VD1 and and VD2.
How can I extract the value of VD1 and VD2 and store it in string.
String test =
"DomainName=xyz.zzz.com
&ModifiedOn=03%2f17%2f2015
&VD1=MTMwMDE3MDQ%3d
&VD2=B67E48F6969E99A0BC2BEE0E240D2B5C
&SiteLanguage=English"
Here value of VD1=MTMwMDE3MDQ%3d and VD2=B67E48F6969E99A0BC2BEE0E240D2B5C. But these are the dynamic values. Here VD1 and VD2 are seperated by '&'.
Try regex like this :
public static void main(String[] args) throws Exception {
String test = "DomainName=xyz.zzz.com&ModifiedOn=03%2f17%2f2015&VD1=MTMwMDE3MDQ%3d&VD2=B67E48F6969E99A0BC2BEE0E240D2B5C&SiteLanguage=English";
Pattern p = Pattern.compile("VD1=(.*)&VD2=(.*)&");
Matcher m = p.matcher(test);
while(m.find()){
System.out.println(m.group(1));
System.out.println(m.group(2));
}
}
O/P :
MTMwMDE3MDQ%3d
B67E48F6969E99A0BC2BEE0E240D2B5C
You can use regular expressions or use the String index() and split() methods.
A regular expression that matches and captures the VD1 value is
/VD1=([^&]*)/
If you're sure that theres always a "&" behind the values of VD1 and VD2, this kind of splitting will do:
String test = "DomainName=xyz.zzz.com&ModifiedOn=03%2f17%2f2015&VD1=MTMwMDE3MDQ%3d&VD2=B67E48F6969E99A0BC2BEE0E240D2B5C&SiteLanguage=English";
String vd1 = test.substring(test.indexOf("VD1=")+4, test.indexOf("&", test.indexOf("VD1")));
String vd2 = test.substring(test.indexOf("VD2=")+4, test.indexOf("&", test.indexOf("VD2")));
System.out.println("VD1:" + vd1 + "\nVD2:" + vd2);
This is only a demo, for production you'd have to extract the indexes for better performance.
You can use String.split(...) to split a String in pieces. For example, test.split("&") first splits the String in individual tokens (of the form "key=value").
You could do the following to achieve this:
String vd1 = null, vd2 = null;
for (String token : test.split("&")) {
// For each token, we check if it is one of the keys we need:
if (token.startsWith("VD1=")) {
// The number 4 represents the length of the String "vd1="
vd1 = token.substring(4);
} else if (token.startsWith("VD2=") {
vd2 = token.substring(4);
}
}
System.out.println("VD1 = " + vd1);
System.out.println("VD2 = " + vd2);
However, if you want to parse arbitrary keys, consider using a more robust solution (instead of hard-coding the keys in the for-loop).
Also see the documentation for the String class
String test = "DomainName=xyz.zzz.com&Test&ModifiedOn=03%2f17%2f2015&VD1=MTMwMDE3MDQ%3d&VD2=B67E48F6969E99A0BC2BEE0E240D2B5C&SiteLanguage=English";
HashMap<String, String> paramsMap = new HashMap<String, String>();
String[] params = test.split("&");
for (int i=0; i<params.length; i++) {
String[] param = params[i].split("=");
String paramName = URLDecoder.decode(param[0], "UTF-8");
String paramValue = null;
if(param.length > 1)
paramValue = URLDecoder.decode(param[1], "UTF-8");
paramsMap.put(paramName, paramValue);
}
String vd1 = paramsMap.get("VD1");
String vd2 = paramsMap.get("VD2");

Getting incorrect output when using the Java method indexof in combination with substring to create a new string

In my program I am trying to split a string at the "," character. After I split the string, I need to create a new string after the "=" character. Then I need to rebuild the string back to its original state. Currently I'm able to split the string and rebuild it to its original state. However when I try to create a new string using the indexof and substring methods, I'm not getting the correct string. I have listed my code below along with my current output and my disired output. Thanks in advance for your help.
public class StringTestProgram {
public static void main(String[] args) {
String relativeDN = "cn=abc,dn=xyz,ou=abc/def";
System.out.println(relativeDN);
//Split String
String[] stringData = relativeDN.split(",");
{
StringBuilder sb = new StringBuilder();
CharSequence charAdded = ",";
// loop thru each element of the array
for (int place = 0; place < stringData.length; place++) {
System.out.println(stringData[place]);
{
int eq = relativeDN.indexOf('=');
String sub = relativeDN.substring(0, eq);
System.out.println(sub);
}
// append element to the StringBuilder
sb.append(stringData[place]);
// avoids adding an extra ',' at the end
if (place < stringData.length - 1)
// if not at the last element, add the ',' character
sb.append(charAdded);
}
System.out.print(sb.toString());
}
}
}
My original string "cn=abc,dn=xyz,ou=abc/def"
My current output:
cn=abc (split string)
cn (create new String)
dn=xyz (split string)
cn (create new String)
ou=abc/def (split string)
cn (create new String)
cn=abc,dn=xyz,ou=abc/def (rebuild String to its original form)
My desired output:
cn=abc (split string)
abc (create new string)
dn=xyz (split string)
xyz (create new String)
ou=abc/def (split string)
abc/def (create new String)
cn=abc,dn=xyz,ou=abc/def (rebuild String to its original form)
Change the following lines:
int eq = relativeDN.indexOf('=');
String sub = relativeDN.substring(0, eq); in your for loop to
int eq = stringData[place].indexOf('=');
String sub = stringData[place].substring(eq+1, stringData[place].length());
You need the separated strings in each iteration so you will need to use stringData[place]. As you were using relativeDN, it was taking your original string in every iteration and was returning cn for each iteration.
Also for printing the string after =, you need to specify the starting location as the location after = and end location as end of string(length) to substring function.
Using Pattern and Matcher classes.
String s = "cn=abc,dn=xyz,ou=abc/def";
String parts[] = s.split(",");
for(String i: parts)
{
System.out.println(i);
Matcher m = Pattern.compile("(?<==).+").matcher(i);
while(m.find())
{
System.out.println(m.group());
}
}
System.out.println(s);
Output:
cn=abc
abc
dn=xyz
xyz
ou=abc/def
abc/def
cn=abc,dn=xyz,ou=abc/def
OR
Using the StringBuilder class.
String relativeDN = "cn=abc,dn=xyz,ou=abc/def";
String[] stringData = relativeDN.split(",");
StringBuilder sb = new StringBuilder();
for(int i =0;i<stringData.length;i++)
{
if(i!=0)
{
sb.append(",");
}
System.out.println(stringData[i]);
int eq = stringData[i].indexOf('=');
String sub = stringData[i].substring(eq+1,stringData[i].length());
System.out.println(sub);
sb.append(stringData[i]);
}
System.out.print(sb.toString());
Output:
cn=abc
abc
dn=xyz
xyz
ou=abc/def
abc/def
cn=abc,dn=xyz,ou=abc/def

void method won't manipulate strings

I have a void method which is supposed to take a String and split it into two strings based on a delimiter. Having used the debugger the method seems to be working correctly, but the two empty strings I pass in for the method to store the results don't seem to be getting updated. I must be doing something idiotic here but any help is appreciated!
public static void main(String[] args) {
String dictFile = "/Users/simonrhillary/Desktop/Dictionary(3).txt";
String synFile = "/Users/simonrhillary/Desktop/Synonyms(2).txt";
fileReader dictFR = new fileReader();
fileReader synFR = new fileReader();
dictFR.filePath = dictFile;
synFR.filePath = synFile;
dictFR.openFile(dictFile);
synFR.openFile(synFile);
String[] dictionary = dictFR.fileToArray();
String[] synonyms = synFR.fileToArray();
String regx = "^[aflmptu]+$";
String regexTemplate = "^[]+$";
String word1 = "";
String word2 = "";
synToWords(synFR.getLine(3), word1, word2);//error seems to be here.
//word1 and word 2 stay ""
System.out.println(word1 +" " + word2);
printArray(findCombos(dictionary, word1, word2));
}
public static void synToWords(String syn, String wordI, String wordII){
String[] words = syn.split("\\t");
wordI = wordI + words[0];
wordII = wordII + words[1];
}
there are other methods I haven't posted but they are all working fine. It's just the synToWords method thats the problem. Many Thanks!
Java passes references by value. So this line:
wordI = wordI + words[0];
assigns a new String to wordI but it is only the local (within the method) copy of the reference which changes. The original word1 variable still refers to the original String.
To make it work, you could use an array instead:
public static void synToWords(String syn, String[] word1And2){
String[] words = syn.split("\\t");
word1And2[0] = word1And2[0] + words[0];
word1And2[1] = word1And2[1] + words[1];
}
and in your main code:
String[] words = { "", "" };
synToWords(synFR.getLine(3), words);
System.out.println(words[0] +" " + words[1]);
Or you could simply return a array of String:
public static String[] synToWords(String syn){
String[] words = syn.split("\\t");
return new String[] {words[0], words[1]};
}
String[] words = synToWords(synFR.getLine(3));
System.out.println(words[0] +" " + words[1]);
Java is entirely call-by-value. wordI and wordII are copies of the values of two reference expressions. A reference expression is either null or a pointer to an object. When you assign to e.g. wordI in synToWords you are only changing what synToWords' local copy points to.
One solution would be to have the method return a String[] containing the two pieces. The caller could then assign elements of the result to its variables.

Categories

Resources