How to convert String to string set in java - java

I have a method with return type as string below is the string which is getting retrieved how should in convert this string to setso that i can iterate through the String set.
["date:#value2","lineofbusiness:#value3","pnrno:#value1","reason:#value4"]
If i try to split using String[] the result is not expected i have to get these individual values like date:#value2 and have to split this to complete the rest of my logic.
How to convert the above string to below string set
Set<String> columnmapping = new HashSet<String>();

I use Apache Commons for string manipulation. Following code helps.
String substringBetween = StringUtils.substringBetween(str, "[", "]").replaceAll("\"", ""); // get rid of bracket and quotes
String[] csv = StringUtils.split(substringBetween,","); // split by comma
Set<String> columnmapping = new HashSet<String>(Arrays.asList(csv));

In addition to the accepted answer there are many options to make it in "a single line" with standards Java Streams (assuming Java >= 8) and without any external dependencies, for example:
String s =
"[\"date:#value2\",\"lineofbusiness:#value3\",\"pnrno:#value1\",\"reason:#value4\"]";
Set<String> strings = Arrays.asList(s.split(",")).stream()
.map(s -> s.replaceAll("[\\[\\]]", ""))
.collect(Collectors.toSet());

Related

String vs StringBuilder

I have a condition like :
public String createId(List<String> list)
{
String id="";
if(list.contains("name"))
id+="TEST VALUE NAME";
if(list.contains("age"))
id+="Test Value AGE";
.
.
. likewise many if condition
return id;
}
As per my understanding we should use StringBuilder in loop condition and String in simple concatenation. So here wanted to ask I should use String or StringBuilder? Kindly suggest
StringBuilder is the best for this scenario because it's mutable. the String is immutable so when you modify the string it creates a new object.
It seems that for the given task it would be better to get rid of the multiple duplicated if statements by defining a list of the keys to match the input list and use Stream API to generate the string id, e.g. Collectors.joining with delimiter or without the delimiter.
Assuming that there is a single rule to create a part of the id: append "Test Value " + key.toUpperCase(), the implementation may look as follows:
final List<String> keys = Arrays.asList(
"name", "age" /* and other needed keys*/
);
public String createId(List<String> list) {
return keys
.stream()
.filter(list::contains)
.map(String::toUpperCase)
.map(str -> "Test Value " + str)
.collect(Collectors.joining("_")); // or Collectors.joining()
}
System.out.println(createId(Arrays.asList("age", "name", "surname")));
// output: Test Value NAME_Test Value AGE
If custom parts should be provided for name, age, etc., a Map of matches should be prepared and used, also it may make sense to convert the input list into Set<String to facilitate look-ups:
final Map<String, String> keys = new LinkedHashMap<>(); {
// fill the map in special order
keys.put("name", "Name Part");
keys.put("age", "Test Age");
/* and other needed keys*/
}
public String createId(List<String> list) {
Set<String> words = new HashSet<>(list);
return keys.keySet()
.stream()
.filter(words::contains) // faster lookup O(1) at the cost of another collection
.map(keys::get)
.collect(Collectors.joining("_")); // or Collectors.joining()
}
System.out.println(createId(Arrays.asList("age", "surname", "name")));
// output: Name Part_Test Age
In general your understanding is correct about when to use String concatenation vs StringBuilder. The Java Language Specification says
To increase the performance of repeated string concatenation, a Java
compiler may use the StringBuffer class or a similar technique to
reduce the number of intermediate String objects that are created by
evaluation of an expression.
For the larger majority of cases you should use whichever method results in better readability and maintainability.

How to extract a part of string starting with a particular string in java

I have a string in java
String s="a=one b=two c=three d=four e=five"
and i want to print the value of c i.e; three.
I took StringTokenizer and i got.
a=one
b=two
c=three
d=four
e=five
and i want to print the value of c i.e; three.
For a one line solution, you could use String#replaceAll:
String input = "a=one b=two c=three d=four e=five";
String cValue = input.replaceAll(".*\\bc=(.+?)\\b.*", "$1");
System.out.println("c: " + cValue);
This prints:
c: three
If you want to go the route of splitting to an array of key value pairs, then consider using streams:
String input = "a=one b=two c=three d=four e=five";
String cValue = Arrays.stream(input.split("\\s+"))
.filter(x -> "c".equals(x.split("=")[0]))
.map(x -> x.split("=")[1])
.collect(Collectors.toList())
.get(0);
In case you know that the letter values are unique, you can convert it to Map, using streams. I wrote a quick method in test package for you
#Test
public void test() {
String s="a=one b=two c=three d=four e=five";
Map<String, String> myMap = Arrays.stream(s.split(" ")).collect(
Collectors.toMap(
key -> key.split("=")[0],
value -> value.split("=")[1]
)
);
System.out.println(myMap.get("c"));
}
How does it work?
It takes your string, splits it first by spaces - as a result you end up with the List of Strings. Then you process it as a stream, use static factory method toMap from Collectors class and split key and value by "=", creating a map (first value as a key, second converted to value) based on this. Then you can get any key value pair You want
Iterate the returned object from StringTokenizer and use the split function to split with = character,
split() will return array, check the 0th index with any character you want (in this case 'c'), if equal, return the 1st index
while (st1.hasMoreTokens()) {
String s = st1.nextToken();
String a[] = s.split("=");
if(a[0) == "c") {
System.out.println(a[1]);
}
}

Parsing String by pattern of substrings

I need to parse a formula and get all the variables that were used. The list of variables is available. For example, the formula looks like this:
String f = "(Min(trees, round(Apples1+Pears1,1)==1&&universe==big)*number";
I know that possible variables are:
String[] vars = {"trees","rivers","Apples1","Pears1","Apricots2","universe","galaxy","big","number"};
I need to get the following array:
String[] varsInF = {"trees", "Apples1","Pears1", "universe", "big","number"};
I believe that split method is good here but can’t figure the regexp required for this.
No need for any regex pattern - just check which item of the supported vars is contained in the given string:
List<String> varsInf = new ArrayList<>();
for(String var : vars)
if(f.contains(var))
varsInf.add(var);
Using Stream<> you can:
String[] varsInf = Arrays.stream(vars).filter(f::contains).toArray(String[]::new);
Assuming "variable" is represented by one alphanumeric character or sequential sequence of multiple such characters, you should split by not-alphanumeric characters, i. e. [^\w]+, then collect result by iteration or filter:
Set<String> varSet = new HashSet<>(Arrays.asList(vars));
List<String> result = new ArrayList<>();
for (String s : f.split("[^\\w]+")) {
if (varSet.contains(s)) {
result.add(s);
}
}

Splitting based on delimiter and string

String CompanyData = "{ChargeCompany1Cnt:0,ChargeCompany2Cnt:73,ChargeCompany3Cnt:44,BalanceCompany3Cnt:0,ChargeCompany4Flag:green,BalanceCompany2Flag:green,BalanceCompany1Cnt:0,ChargeCompany3Flag:red,ChargeCompany1Flag:green,BalanceCompany4Flag:green,BalanceCompany1Flag:green,BalanceCompany2Cnt:0,BalanceCompany4Cnt:0,BalanceCompany3Flag:green,ChargeCompany2Flag:red,ChargeCompany4Cnt:6}";
CompanyData is my string I am splitting the data like below. There is no issue with this code, but if the order is changed in the string splitting is breaking.
how to split this string and assign to another string by its name(like splitting based on ChargeCompany1Cnt, ChargeCompany2Cnt). i have used cut and sed commands in UNIX to do this, right now converting my Shell script into JAVA. So sorry if it's a basic question
String ChargeCompany1Cnt=CompanyData.split(,)[0].replace("{","");
String ChargeCompany2Cnt=CompanyData.split(,)[1];
String ChargeCompany3Cnt=CompanyData.split(,)[2];
String BalanceCompany3Cnt=CompanyData.split(,)[3];
String ChargeCompany1Flag=CompanyData.split(,)[8];
Basically I need to find String like ChargeCompany2Cnt,ChargeCompany1Flag in CompanyData and print ChargeCompany2Cnt:73 ChargeCompany1Flag:green
Please note if this is JSON object you can parse it easily with ObjectMapper
of Jacson. you can use the below code for manual parsing
String CompanyData = "{ChargeCompany1Cnt:0,ChargeCompany2Cnt:73,ChargeCompany3Cnt:44,BalanceCompany3Cnt:0,ChargeCompany4Flag:green,BalanceCompany2Flag:green,BalanceCompany1Cnt:0,ChargeCompany3Flag:red,ChargeCompany1Flag:green,BalanceCompany4Flag:green,BalanceCompany1Flag:green,BalanceCompany2Cnt:0,BalanceCompany4Cnt:0,BalanceCompany3Flag:green,ChargeCompany2Flag:red,ChargeCompany4Cnt:6}";
HashMap<String,String> mymap = new HashMap<String,String>();
for ( String s: CompanyData.split("[?,{}]")) {
if (!s.equals(""))
mymap.put(s.split(":")[0],s.split(":")[1]); }
for (HashMap.Entry<String, String> entry : mymap.entrySet()) {
String key = entry.getKey().toString();;
String value = entry.getValue();
System.out.println( key + " = " + value );
Your question isn't too clear, but perhaps this snippet will point you in the right direction:
List<String> companyCount = new ArrayList<>();
String[] companies = CompanyData.substring(1, -1).split(",");
for (String companyCnt : companies) {
companyCount.add(companyCnt);
}
Incidentally, you can probably perform this whole operation without use of cut(1) as well.
Depending on how you intend to use the variables you could alternatively create a set of key-value pairs instead of explicitly declaring each variable.
Then you could split the names out (i.e. split each element further on :) and use them as keys without needing to know which is which.

How to split string using regular expression and put string values into a map in Java

I have a following String and i want to read it using regular expression and put into a map as a key and value.I have already split and put into a map.but the problem is that i have used string arrays and there is a high risk of array index out of bound.so i think that way is not suit for good coding.
public static void read(String log,Map<String, String> logMap) {
String sanitizeLog = "";
String commaSeparatedLine[];
String equalSeparatedLine[];
String patternComma = ",";
String patternEqual = "=";
String patternSanitize = "(?<=]:).*";
Pattern pattern = Pattern.compile(patternSanitize);
Matcher matcher = pattern.matcher(log);
if (matcher.find()) {
sanitizeLog = matcher.group();
}
pattern = Pattern.compile(patternComma);
commaSeparatedLine = pattern.split(sanitizeLog);
for (String line : commaSeparatedLine) {
pattern = Pattern.compile(patternEqual);
equalSeparatedLine = pattern.split(line);
for (int i = 0; i < equalSeparatedLine.length; i += 2) {
logMap.put(equalSeparatedLine[i].trim(),
equalSeparatedLine[i + 1]);
}
}
}
Above code snippet is working fine.but there i used lot of string arrays to store split values.Please let me know that is there any way to do the same thing without using string arrays and put split values in to a map using regular expression.I am a newbie in regular expression.
Output Map should contain like this.
Key -> value
DB.UPDATE_CT -> 2
DB.DUPQ_CT -> 1
...
String value to be split
[2015-01-07 07:17:56,911]: R="InProgressOrders.jsp", REQUEST_UUID="77ed2ab1-b799-4715-acd5-e77ab756192e", HTTP_M="POST",
PFWD="login.jsp", USER_ORG="TradeCustomer.1717989", TX_ORG1="1717989",
DB.QUERY_CT=61, DB.UPDATE_CT=2, DB.DUPQ_CT=1, DB.SVR_MS=59,
DB.IO_MS=111, DB.DRV_MS=144, DB.LOCK_MS=31, DB.BYTES_W=1501, KV.PUT=1,
KV.GET=5, KV.PWAIT_MS=2, KV.GWAIT_MS=4, KV.BYTES_W=193,
KV.BYTES_R=367, MCACHE.GET=30, MCACHE.PUT=18, MCACHE.L1HIT=10,
MCACHE.L2HIT=1, MCACHE.HIT=1, MCACHE.MISS=18, MCACHE.WAIT_MS=51,
MCACHE.BYTES_W=24538, MCACHE.BYTES_R=24282, ROOTS.READ_CT=6,
ROOTS.DUPRSV_CT=3, THREAD.WALL_MS=594, THREAD.CPU_MS=306,
THREAD.CPU_USER_MS=300, THREAD.MEM_K=19318
You seem to have a lot of code. Here is how to do it in 1-line:
Map<String, String> map = Arrays.stream(input.split(","))
.map(s -> a.split("="))
.collect(Collectors.toMap(a -> a[0], a -> a[1]));
To instead add the entries to another map (as in your code):
Arrays.stream(input.split(",")).map(s -> a.split("="))
.forEach(a -> logMap.put(a[0], a[1]));
Disclaimer: Not tested or compiled, just thumbed in.

Categories

Resources