Block Integer parsing of a string if it contains a decimal point.#25
Conversation
|
Hi - Any feedback on this pr? |
If group 4 is non-null, it means an exponent part was found.
aa54f8c to
e323c0a
Compare
|
Thanks @JaredDavis22! And apologies for the delay in recent reviews. Always a lot going on. |
|
I just triggered the release of parsington 3.3.0 with all the recently merged PRs. Should show up on Maven Central in a few minutes, barring CI complaints. |
JaredDavis22
left a comment
There was a problem hiding this comment.
I believe start()==-1 is faster than group()=null. Group creates a new string that is then thrown away.
(m.start(3)==-1) && (m.start(4)==-1) ?
A quick and dirty test shows start is a little faster than group. Since this code executes a lot, it makes sense to use the .start format.
output of dirty test: (longer time is worse)
using group()=null stop. good=3500000 exceptions=0 time=0.965323396
using .start: stop. good=3500000 exceptions=0 time=0.654254639
public static void main(String[] args) {
final Pattern DECIMAL = Pattern.compile(
"(([-+]?[0-9]+(\\.[0-9]*)?([Ee][-+]?[0-9]+)?)([DdFfLl])?).*");
final Matcher matcher = DECIMAL.matcher("");
double[] doubles = {1.4, 1.8, 100.56, 3438535,43534545.67575 ,};
int[] ints = {14, 18, 10056, 34385,43534545 ,};
String[] parseThis = new String[doubles.length*2];
for (int x = 0; x < doubles.length; x++) {
parseThis[x] = String.valueOf(doubles[x]);
parseThis[x+ doubles.length] = String.valueOf(ints[x]);
}
{
int count =0;
int good = 0;
final long startTime = System.nanoTime();
boolean ignored;
for (int i = 0; i < 7000000; i++) {
try {
String p = parseThis[i % 10];
matcher.reset(p);
ignored = matcher.matches();
if ((matcher.group(3) == null) && (matcher.group(4) == null)) {
Integer.parseInt(p);
good++;
}
} catch (NumberFormatException e) {
// eat it
count++;
}
}
final long elapsed = System.nanoTime() - startTime;
System.out.println("using group()=null stop. good=" + good + " exceptions=" + count + " time=" + elapsed / 1000000000.0);
}
{
int count =0;
int good = 0;
final long startTime = System.nanoTime();
boolean ignored;
for (int i = 0; i < 7000000; i++) {
try {
String p = parseThis[i % 10];
matcher.reset(p);
ignored = matcher.matches();
if ((matcher.start(3) == -1) && (matcher.start(4) == -1)) {
Integer.parseInt(p);
good++;
}
} catch (NumberFormatException e) {
// eat it
count++;
}
}
final long elapsed = System.nanoTime() - startTime;
System.out.println("using .start: stop. good=" + good + " exceptions=" + count + " time=" + elapsed / 1000000000.0);
}
|
Matcher.java from openjdk It looks like to me that start will be faster when the group exists. https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/regex/Matcher.java |
|
@JaredDavis22 Updated! I used |
|
Thanks. I'm ok with leaving it as < 0. I also believe == or < will perform the same on ints. fyi: |
Small change improved the performance of the code for my usage.
Does the current code handle decimal numbers with a comma?
eg 10,001 for 10.001
This change will do nothing for those cases.
Quick test below showing the impact of generating the exception.
stop. good=350000 exceptions=0 time=0.022590425
change one line
stop. good=350000 exceptions=350000 time=0.436176896