Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splitting a String works in Java, doesn't work on Android

So I have this logic which splits a String by 4 characters each. Something like this

0108011305080508000000 gives 0108 0113 0508 0508 0000 00

The logic I used is

String [] splitErrorCode = inputString.split("(?<=\\G....)");

It works great in Java, but when I run it in Android I get the wrong output.

0108 011305080508000000

I have no clue what is going wrong. After a going through the String's split function, I realized Android uses fastSplit where as the Java version has a huge splitting logic.

Aren't both the functions supposed to work identically? Why is this a problem? Any comments/ suggestions?

like image 243
iZBasit Avatar asked Dec 29 '14 14:12

iZBasit


People also ask

Why split is not working for dot in Java?

backslash-dot is invalid because Java doesn't need to escape the dot. You've got to escape the escape character to get it as far as the regex which is used to split the string. eg.

What is split in Android?

In Android 7.0 and later, users can have multiple apps simultaneously displayed on their device screen with the platform feature multi-window. The default mode is split-screen, which provides two activity panes for users to place apps.

Does split work in Java?

Split() String method in Java with examples. The string split() method breaks a given string around matches of the given regular expression. After splitting against the given regular expression, this method returns a string array.


1 Answers

\G in Java was added in Java 6 to mimic the Perl construct:

http://perldoc.perl.org/perlfaq6.html#What-good-is-%5CG-in-a-regular-expression:

You use the \G anchor to start the next match on the same string where the last match left off.

Support for this was very poor. This construct is documented in Python to be used in negative variable-length lookbehinds to limit how far back the lookbehind goes. Explicit support was added.

However, the split method in JDK 7 has a fast path for the common case where the limit is a single character. This avoids the need to compile or to use regex. Here is the method (detail source redacted):

public String[] split(String regex, int limit) {
    /* fastpath if the regex is a
     (1)one-char String and this character is not one of the
        RegEx's meta characters ".$|()[{^?*+\\", or
     (2)two-char String and the first char is the backslash and
        the second is not the ascii digit or ascii letter.
     */
    char ch = 0;
    if (((regex.value.length == 1 &&
         ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
         (regex.length() == 2 &&
         /* Fast path checks as documented in the comment */ )
    {
        // Fast path computation redacted!
        String[] result = new String[resultSize];
        return list.subList(0, resultSize).toArray(result);
    }
    return Pattern.compile(regex).split(this, limit);
}

And before:

public String[] split(String regex, int limit) {
    return Pattern.compile(regex).split(this, limit);
}

While this fastpath exists, note that deploying Android programs means it must have source compatibility with Java 6. The Android environment is unable to take advantage of the fast path, therefore it delegates to fastSplit and loses some of the Perl construct supports, such as \A.

As for why they didn't like the traditional always-regex path, it's kind of obvious by itself.

like image 119
Unihedron Avatar answered Oct 05 '22 07:10

Unihedron