I have been given a string:
00122334455667788990875645346787659870984780...
the above given string size will always be even. i have to implement a method which will return an Arraylist of String where each element will contain 2 chars. for example for above string:
1st position of arraylist will contain: 00
2nd: 12
3rd: 23
...
I have tried to implement it myself, this is how my functions looks like:
private static ArrayList<String> getArrayListFrom(String data) {
if(data.length()%2==0){
ArrayList<String> aList = new ArrayList<String>();
char[] dArray = data.toCharArray();
//logic here.
for(int i = 0; i < dArray.length + 2; i = i+2){
if(i != 0){
aList.add(dArray[i-2]+""+dArray[i-1]);
}
}
return aList;
}else{
System.out.println("Invalid data.");
return null;
}
}
This URL suggests that simple iteration is more efficient in this case. do you guys agree ?
You can do this with a single split (Well, this may not be most efficient at runtime, but this is concise, lesser code to write):
String[] arr = str.split("(?<=\\G..)");
And then get the List<String>
using Arrays#asList()
method.
The regex pattern splits on an empty space preceded by 2 characters - ..
, but ignoring the character already considered in previous match - \\G
. The anchor \\G
matches at the position where the previous match ended.
String str = "00122334455667788990875645346787659870984780";
String[] arr = str.split("(?<=\\G..)");
System.out.println(Arrays.asList(arr));
prints:
[00, 12, 23, 34, 45, 56, 67, 78, 89, 90, 87, 56, 45, 34, 67, 87, 65, 98, 70, 98, 47, 80]
Here's how split is done on your string:
" 00 1 2 2334455667788990875645346787659870984780" (whitespaces represent empty string)
// | | |
// split, no-split, split -> gives 12
// | | | |
// \ / \ /
// gives 00 as the preceding two characters are `1` and `0`.
// but 0 is already considered for the previous empty string
Reference:
If runtime performance is an issue, then you can go with simple looping:
String str = "00122334455667788990875645346787659870984780";
List<String> list = new ArrayList<String>();
for (int i = 0; i < str.length(); i += 2) {
list.add(str.substring(i, i + 2));
}
System.out.println(list);
But you can check for yourself, whether the regex split is really a performance bottleneck for large string, and benchmark both of them appropriately.
I benchmarked both the methods - split, and loop. And as expected loop is almost 4-5 times more efficient than split for a string of length say 1000
.
public static void usingSplit(String str) {
String[] arr = str.split("(?<=\\G..)");
List<String> list = Arrays.asList(arr);
}
public static void usingLoop(String str) {
List<String> list = new ArrayList<String>();
for (int i = 0; i < str.length(); i += 2) {
list.add(str.substring(i, i + 2));
}
}
// Warm up JVM
for (int i = 0; i < 1000000; ++i) {
usingSplit(str);
}
for (int j = 0; j < 1000000; j++) {
usingLoop(str);
}
long nano = System.nanoTime();
for (int i = 0; i < 1000000; ++i) {
usingSplit(str);
}
System.out.println("Time with usingSplit(): " + (System.nanoTime() - nano) * 1.0 / Math.pow(10, 9) + " Seconds");
nano = System.nanoTime();
for (int j = 0; j < 1000000; j++) {
usingLoop(str);
}
System.out.println("Time with usingLoop(): " + (System.nanoTime() - nano) * 1.0 / Math.pow(10, 9) + " Seconds");
Output on few successive runs:
Run 1:
Time with usingSplit(): 34.391315143 Seconds
Time with usingLoop(): 7.515221612 Seconds
Run 2:
Time with usingSplit(): 33.41518869 Seconds
Time with usingLoop(): 7.868896218 Seconds
If someone thinks that the benchmark result is flawed, then please make a note of it in comments.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments