How to create a string from many strings efficiently in Java - java

In a Java code, I have 11 different strings, some of them (at most 9) can be null. Strings are a part of an object. If none of them is null, I make a string like this :
string1 + "," + string2 + "," + string3 + "," + string4 + "," + string5 + "," + string6 + "(" + string7 + ")" + string8 + string9 + "+" + string10 + string11
If none of them is null, it's okey. But some of them can be null. If I check if each of them is null, code gets really slow and long. How can I generate such a string in an efficient and fast way? Thanks.

public static void main(String[] args) {
String string1 = "test1";
String string2 = "test2";
String string3 = "test3";
String string4 = null;
String string5 = "test5";
StringBuilder stringBuilder = new StringBuilder();
List<String> valueList = new ArrayList<>();
valueList.add(string1);
valueList.add(string2);
valueList.add(string3);
valueList.add(string4);
valueList.add(string5);
// etc.
for (String value : valueList) {
if (value != null) {
stringBuilder.append(value);
}
else {
value = ",";
stringBuilder.append(value);
}
}
System.out.println(stringBuilder);
}
Output :
test1test2test3,test5

With Java 8 you could use this for the first part with comma-delimited strings:
String part1 = Stream.of(string1, string2, string3, string4, string5, string6)
.filter(Objects.notNull())
.collect(joining(",");
From then on you have an irregular structure so you'll need custom logic to handle it. The helper function
static String emptyForNull(String s) {
return s == null ? "" : s;
}
can get you part of the way.

In Java 8, you can stream and join with Collectors, and filter with Objects classes
List<String> strings = Arrays.asList("first", "second", null, "third", null, null, "fourth");
String res = strings.stream().filter(Objects::nonNull).collect(Collectors.joining(","));
System.out.println(res);
results in output
first,second,third,fourth

If you simply want your code to be as short as possible, use String.format and get rid of the "null" in the string.
String result = String.format("%s,%s,%s,%s,%s,%s(%s)%s,%s,%s,%s",
string1, string2, string3, string4, string5,
string6, string7, string8, string9, string10,
string11);
System.out.println(result.replace("null", ""));

If 6th index of your string is always surrounded by ( and ) then you can use following code.
List<String> vals = new ArrayList<>();
vals.add(string1);
vals.add(string2);
vals.add(string3);
vals.add(string4);
vals.add(string5);
vals.add(string6);
vals.add(string7);
vals.add(string8);
vals.add(string9);
vals.add(string10);
vals.add(string11);
for (int i =0 ; i < vals.size(); i++) {
// check null values
if (vals.get(i) != null) {
// as your requirement surround 7th value with ( and )
if(vals.indexOf(vals.get(i)) == 6) {
values += "\b(" + vals.get(i)+")";
} else {
values += vals.get(i)+",";
}
}
}
System.out.println(values+"\b");
Output
if 4th and 9th strings are null then,
test1,test2,test3,test5,test6(test7)test8,test10,test11

Related

Split String from the last iteration

This post is an update to this one : get specific character in a string with regex and remove unused zero
In the first place, i wanted to remove with an regular expression the unused zero in the last match.
I found that the regular expression is a bit overkill for what i need.
Here is what i would like now,
I would like to use split() method
to get from this :
String myString = "2020-LI50532-3329-00100"
this :
String data1 = "2020"
String data2 = "LI50532"
String data3 = "3329"
String data4 = "00100"
So then i can remove from the LAST data the unused Zero
to convert "00100" in "100"
And then concatenate all the data to get this
"2020-LI50532-3329-100"
Im not familiar with the split method, if anyone can enlight me about this ^^
You can use substring method to get rid of the leading zeros...
String myString = "2020-LI50532-3329-00100";
String[] data = myString.split("-");
data[3] = data[3].substring(2);
StringBuilder sb = new StringBuilder();
sb.append(data[0] + "-" + data[1] + "-" + data[2] + "-" + data[3]);
String result = sb.toString();
System.out.println(result);
Assuming that we want to remove the leading zeroes of ONLY the last block, maybe we can:
Extract the last block
Convert it to Integer and back to String to remove leading zeroes
Replace the last block with the String obtained in above step
Something like this:
public String removeLeadingZeroesFromLastBlock(String text) {
int indexOfLastDelimiter = text.lastIndexOf('-');
if (indexOfLastDelimiter >= 0) {
String lastBlock = text.substring(indexOfLastDelimiter + 1);
String lastBlockWithoutLeadingZeroes = String.valueOf(Integer.valueOf(lastBlock)); // will throw exception if last block is not an int
return text.substring(0, indexOfLastDelimiter + 1).concat(lastBlockWithoutLeadingZeroes);
}
return text;
}
Solution using regex:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(parse("2020-LI50532-3329-00100"));
System.out.println(parse("2020-LI50532-3329-00001"));
System.out.println(parse("2020-LI50532-03329-00100"));
System.out.println(parse("2020-LI50532-03329-00001"));
}
static String parse(String str) {
return str.replaceAll("0+(?=[1-9]\\d*$)", "");
}
}
Output:
2020-LI50532-3329-100
2020-LI50532-3329-1
2020-LI50532-03329-100
2020-LI50532-03329-1
Explanation of the regex:
One or more zeros followed by a non-zero digit which can be optionally followed by any digit(s) until the end of the string (specified by $).
Solution without using regex:
You can do it also by using Integer.parseInt which can parse a string like 00100 into 100.
public class Main {
public static void main(String[] args) {
// Test
System.out.println(parse("2020-LI50532-3329-00100"));
System.out.println(parse("2020-LI50532-3329-00001"));
System.out.println(parse("2020-LI50532-03329-00100"));
System.out.println(parse("2020-LI50532-03329-00001"));
}
static String parse(String str) {
String[] parts = str.split("-");
try {
parts[parts.length - 1] = String.valueOf(Integer.parseInt(parts[parts.length - 1]));
} catch (NumberFormatException e) {
// Do nothing
}
return String.join("-", parts);
}
}
Output:
2020-LI50532-3329-100
2020-LI50532-3329-1
2020-LI50532-03329-100
2020-LI50532-03329-1
you can convert the last string portion to integer type like below for removing unused zeros:
String myString = "2020-LI50532-3329-00100";
String[] data = myString.split("-");
data[3] = data[3].substring(2);
StringBuilder sb = new StringBuilder();
sb.append(data[0] + "-" + data[1] + "-" + data[2] + "-" + Integer.parseInt(data[3]));
String result = sb.toString();
System.out.println(result);
You should avoid String manipulation where possible and rely on existing types in the Java language. One such type is the Integer. It looks like your code consists of 4 parts - Year (Integer) - String - Integer - Integer.
So to properly validate it I would use the following code:
Scanner scan = new Scanner("2020-LI50532-3329-00100");
scan.useDelimiter("-");
Integer firstPart = scan.nextInt();
String secondPart = scan.next();
Integer thirdPart = scan.nextInt();
Integer fourthPart = scan.nextInt();
Or alternatively something like:
String str = "00100";
int num = Integer.parseInt(str);
System.out.println(num);
If you want to reconstruct your original value, you should probably use a NumberFormat to add the missing 0s.
The main points are:
Always try to reuse existing code and tools available in your language
Always try to use available types (LocalDate, Integer, Long)
Create your own types (classes) and use the expressiveness of the Object Oriented language
public class Test {
public static void main(String[] args) {
System.out.println(trimLeadingZeroesFromLastPart("2020-LI50532-03329-00100"));
}
private static String trimLeadingZeroesFromLastPart(String input) {
String delem = "-";
String result = "";
if (input != null && !input.isEmpty()) {
String[] data = input.split(delem);
StringBuilder tempStrBldr = new StringBuilder();
for (int idx = 0; idx < data.length; idx++) {
if (idx == data.length - 1) {
tempStrBldr.append(trimLeadingZeroes(data[idx]));
} else {
tempStrBldr.append(data[idx]);
}
tempStrBldr.append(delem);
}
result = tempStrBldr.substring(0, tempStrBldr.length() - 1);
}
return result;
}
private static String trimLeadingZeroes(String input) {
int idx;
for (idx = 0; idx < input.length() - 1; idx++) {
if (input.charAt(idx) != '0') {
break;
}
}
return input.substring(idx);
}
}
Output:
2020-LI50532-3329-100

Split and pair substrings by condition

I have a string like this: "aa-bb,ccdd,eeff,gg-gg,cc-gg". I need to split the string by '-' signs and create two strings from it, but if the comma-delimited part of the original string doesn't contain '-', some placeholder character needs to be used instead of substring. In case of above example output should be:
String 1:
"{aa,ccdd,eeff,gg,cc}"
String 2:
"{bb,0,0,gg,gg}"
I can't use the lastIndexOf() method because input is in one string. I am not sure how to much the parts.
if(rawIndication.contains("-")){
String[] parts = rawIndication.split("-");
String part1 = parts[0];
String part2 = parts[1];
}
Here is a Java 8 solution, using streams. The logic is to first split the input string on comma, generating an array of terms. Then, for each term, we split again on dash, retaining the first entry. In the case of a term having no dashes, the entire string would just be retained. Finally, we concatenate back into an output string.
String input = "aa-bb,ccdd,eeff,gg-gg,cc-gg";
int pos = 1;
String output = String.join(",", Arrays.stream(parts)
.map(e -> e.split("-").length >= (pos+1) ? e.split("-")[pos] : "0")
.toArray(String[]::new));
System.out.println(output);
This outputs:
bb,0,0,gg,gg
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
// First split the source String by comma to separate main parts
String[] mainParts = sourceStr.split(",");
for (String mainPart: mainParts) {
// Check if each part contains '-' character
if (mainPart.contains("-")) {
// If contains '-', split and add the 2 parts to 2 arrays
String[] subParts = mainPart.split("-");
list1.add(subParts[0]);
list2.add(subParts[1]);
} else {
// If does not contain '-', add complete part to 1st array and add placeholder to 2nd array
list1.add(mainPart);
list2.add("0");
}
}
// Build the final Strings by joining String parts by commas and enclosing between parentheses
String str1 = "{" + String.join(",", list1) + "}";
String str2 = "{" + String.join(",", list2) + "}";
System.out.println(str1);
System.out.println(str2);
With the way you structured the problem, you should actually be splitting by commas first. Then, you should iterate through the result of the call to split and split each string in the outputted array by hyphen if there exists one. If there isn't a hyphen, then you can add a 0 to string 2 and the string itself to string 1. If there is a hyphen, then add the left side to string 1 and the right side to string 2. Here's one way you can do this,
if(rawIndication.contains(",")){
String s1 = "{";
String s2 = "{";
String[] parts = rawIndication.split(",");
for(int i = 0; i < parts.length; i++) {
if(parts[i].contains("-") {
String[] moreParts = parts[i].split(",");
s1 = s1 + moreParts[0] + ",";
s2 = s2 + moreParts[1] + ",";
}
else{
s1 = s1 + parts[i] + ",";
s2 = "0,";
}
}
s1 = s1.substring(0, s1.length() - 1); //remove last extra comma
s2 = s2.substring(0, s2.length() - 1); //remove last extra comma
s1 = s1 + "}";
s2 = s2 + "}";
}
I think this solves your problem.
private static void splitStrings() {
List<String> list = Arrays.asList("aa-bb", "ccdd", "eeff", "gg-gg", "cc-gg");
List firstPartList = new ArrayList<>();
List secondPartList = new ArrayList<>();
for (String undividedString : list){
if(undividedString.contains("-")){
String[] dividedParts = undividedString.split("-");
String firstPart = dividedParts[0];
String secondPart = dividedParts[1];
firstPartList.add(firstPart);
secondPartList.add(secondPart);
} else{
firstPartList.add(undividedString);
secondPartList.add("0");
}
}
System.out.println(firstPartList);
System.out.println(secondPartList);
}
Output is -
[aa, ccdd, eeff, gg, cc]
[bb, 0, 0, gg, gg]

Change order of words Java

I cannot figure out how to change the order of a given name.
For example: Van-Dame Claud
Result: Claud Dame-Van
I created this method, but it seems that is not correct, any suggestion or maybe a better method?
public String NameInvers(){
String Name, Name = null, Name = null, NameFinal;
int s1 = getName().indexOf(' ');
int s2 = getName().indexOf('-');
if(s1 != 0){
Name1 = getName().substring(0, s1);
if(s2 != 0)
{
Name2 = getName().substring(s1, s2);
Name3 = getName().substring(s2);
}
NameFinal = Name3 + Name2 + Name1;
}
else
NameFinal = getName();
return NameFinal;
}
Edit: In my Main method I have a number of names. The thing is that it says: throw new StringIndexOutOfBoundsException(subLen) and it won't show up.
Here you go:
public static String reverseName (String name) {
name = name.trim();
StringBuilder reversedNameBuilder = new StringBuilder();
StringBuilder subNameBuilder = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
char currentChar = name.charAt(i);
if (currentChar != ' ' && currentChar != '-') {
subNameBuilder.append(currentChar);
} else {
reversedNameBuilder.insert(0, currentChar + subNameBuilder.toString());
subNameBuilder.setLength(0);
}
}
return reversedNameBuilder.insert(0, subNameBuilder.toString()).toString();
}
Test:
public static void main(String[] args) {
printTest("Van-Dame Claud");
printTest("Victor Hugo");
printTest("Anna");
printTest("");
}
private static void printTest(String S) {
System.out.printf("Reverse name for %s: %s\n", S, reverseName(S));
}
Output:
Reverse name for Van-Dame Claud: Claud Dame-Van
Reverse name for Victor Hugo: Hugo Victor
Reverse name for Anna: Anna
Reverse name for :
First of all, you duplicate your variable Name declaration, three times. I suppose that you want to put:
String Name1, Name2 = null, Name3 = null, NameFinal;
instead of:
String Name, Name = null, Name = null, NameFinal;
Then, if you just have 2 names with a - in the middle and you want to change their order you can use split function to separate it, finding where - is. You can use it like this:
String string = "Van-Dame Claud";
String[] divide = string.split("-");
String Name1 = divide[0];
String Name2 = divide[1];
String result = Name2 + "-" + Name1;
EDIT: Name1 will be Van and Name2 will be Dame Claud so the result will be Dame Cloud-Van.
I expect it works for you!
You want to have a method to convert all names or just the the names in form of Name-Name Name? I'm assuming you want a method for all names. Since if you just want to reverse names in this specific form, there is no meaning for you to check value of s1 and s2, you know s1 and s2 must be a positive number. If you check because you want to do error checking, then you should throw an exception if the name is not in the form you want. If you want to do it for all names, below is the pseudocode, you can implement it yourself (your code contains several errors, you are using Name1, Name2, Name3, but you never declared them and duplicate variable Name declaration):
string finalName = ""
string [] strs1 = name split by " "
foreach str1 in strs1
string [] strs2 = str1 split by "-"
foreach str2 in strs2
if str2.first?
finalName = str2 + " " + finalName
else
finalName = str2 + "-" + finalName
end
end
end
return finalName.substring 0, finalName.length-1 //remove the space at the end
I think this would work. Hope you find it useful.

printing a split string

I am trying to print my string in the following format. ua, login, login ---> ua, navigation, fault Average = 500 milliseconds. I am storing the 2 strings into one string called keyString and putting it into the hashmap seperated by "|". I am then splitting that when I am iterating over the keyset to get it in the format I originally stated but it is showing up like this ---> ua, ctiq, export|ua, ctiq export, transfer Average = 600 milliseconds. Any ideas?
public static void ProcessLines(Map<String, NumberHolder> uaCount,String firstLine, String secondLine) throws ParseException
{
String [] arr1 = firstLine.split("-- ", 2);
String [] arr2 = secondLine.split("-- ", 2);
String str1 = arr1[1];
String str2 = arr2[1];
......
String keyString = str1 + "|" + str2;
NumberHolder hashValue = uaCount.get(keyString);
if(hashValue == null)
{
hashValue = new NumberHolder();
uaCount.put(keyString, hashValue);
}
hashValue.sumtime_in_milliseconds += diffMilliSeconds;
hashValue.occurences++;
public static class NumberHolder
{
public int occurences;
public int sumtime_in_milliseconds;
}
and heres the printing part
for(String str : uaCount.keySet())
{
String [] arr = str.split("|",2);
long average = uaCount.get(str).sumtime_in_milliseconds / uaCount.get(str).occurences;
//System.out.println(str);
System.out.println(arr[0] + " ---> " + arr[1] + " Average = " + average + " milliseconds");
}
split uses regular expression to match place to split, and in "RegEx" | means OR. To use | as literal you need to escape it with \ which in String is written as "\\". Alternatively you can use [|]. Try
str.split("\\|",2);

Code for searching in a String if it contains a Char[] array?

I'm developing an app that has a feature to search a text (searchString ) in Arabic language if it is in a .txt file (.txt file is also in Arabic language).
Since Android doesn't support Arabic 100%, String.indexof() doesn't work properly. So, I thought, I would put the searchString into a Char[] array and instead of comparing the whole word, I compare every character. So I put the searchString into a char[] and start comparing the array to the String
Is it available anywhere a code that searches if the sequence that is in the char[] array is into a String?
example:
char[]={t,e,s,t} String1{qqwtestq} String2{qwqtqwe} -> String1:TRUE String2:FALSE
Thanks
indexOf and contains don't use character encoding of any sort and you can use characters which are not used in your character encoding for example. i.e. it is ignored for these functions.
All String.indexOf() and contains do is compare character for character. I am not sure what behaviour you are expecting for 100% Arabic support. Here is a simplified version what the indexOf()/contains() does
public static int indexOf(String string, char[] chars) {
LOOP:
for (int i = 0; i < string.length() - chars.length; i++) {
for (int j = 0; j < chars.length; j++)
if (string.charAt(i + j) != chars[j])
continue LOOP;
return i;
}
return -1;
}
public static void main(String args[]) {
char[] chars = "test".toCharArray();
String one = "qqwtestq";
String two = "qwqtqwe";
String str = new String(chars);
System.out.println("indexOf(" + one+", " + Arrays.toString(chars) + ") = " + indexOf(one, chars));
System.out.println(one + ".indexOf(" + str + ") = " + one.indexOf(str));
System.out.println("indexOf(" + two+", " + Arrays.toString(chars) + ") = " + indexOf(two, chars));
System.out.println(two + ".indexOf(" + str + ") = " + two.indexOf(str));
char[] chars2 = { '\uffff', '\uFeFF' };
String test = "qqw\uffff\uFeFFq";
String str2 = new String(chars2);
System.out.println("indexOf(" + test+", " + Arrays.toString(chars2) + ") = " + indexOf(test, chars2));
System.out.println(test + ".indexOf(" + str2 + ") = " + test.indexOf(str2));
}
Prints
indexOf(qqwtestq, [t, e, s, t]) = 3
qqwtestq.indexOf(test) = 3
indexOf(qwqtqwe, [t, e, s, t]) = -1
qwqtqwe.indexOf(test) = -1
indexOf(qqw??q, [?, ?]) = 3
qqw??q.indexOf(??) = 3
Can you provide an example where this method doesn't work?
EDIT: This test checks every possible character to see if indexOf behaves as expected. i.e. the same for every possible character.
for(int i=Character.MIN_VALUE;i<= Character.MAX_VALUE;i++) {
String find = new String(new char[] {(char) i});
String str = new String(new char[] {(char) (i+1), (char) i});
String str1 = new String(new char[] {(char) (i+1)});
int test1 = str.indexOf(find);
if (test1 != 1)
throw new AssertionError("test1 failed i="+i);
int test2 = str1.indexOf(find);
if (test2 != -1)
throw new AssertionError("test2 failed i="+i);
}
Finds no discrepancies.
Implement KMP!
http://en.m.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm
EDIT
Sorry, I did not know about Arabic on Android. Some suggestions point to Cyanogen, and that only Android 3.0 supports Arabic.
Try StringUtils contains method.
How about this?
char[] ch = { 't', 'e', 's', 't' };
String string1 = "qqwtestq";
if (string1.contains((new StringBuffer()).append(ch)))
System.out.println("true");
else
System.out.println("false");

Categories

Resources