Konrad Garus
Konrad Garus

Reputation: 54025

String.split() *not* on regular expression?

Since String.split() works with regular expressions, this snippet:

String s = "str?str?argh";
s.split("r?");

... yields: [, s, t, , ?, s, t, , ?, a, , g, h]

What's the most elegant way to split this String on the r? sequence so that it produces [st, st, argh]?

EDIT: I know that I can escape the problematic ?. The trouble is I don't know the delimiter offhand and I don't feel like working this around by writing an escapeGenericRegex() function.

Upvotes: 81

Views: 30032

Answers (8)

Stephen C
Stephen C

Reputation: 718906

A general solution using just Java SE APIs is:

String separator = ...
s.split(Pattern.quote(separator));

The quote method returns a regex that will match the argument string as a literal.


Commenters have noted that there are scenarios in which using Pattern.compile and caching the resulting Matcher has performance benefits. But the counter to that is that there are scenarios where it is not beneficial (or the benefit is insignificant). And in a multi-threaded application, sharing a Matcher across multiple threads is potentially problematic because Matcher is not thread-safe. The bottom line is that discussion of using Pattern.compile (or not) is a red herring in the context of the question asked.

Upvotes: 111

Alex Wittig
Alex Wittig

Reputation: 2900

org.apache.commons.lang.StringUtils has methods for splitting Strings without expensive regular expressions.

Be sure to read the javadocs closely as the behavior can be subtle. StringUtils.split (as in another answer) does not meet the stated requirements. Use StringUtils.splitByWholeSeparator instead:

String s = "str?str?argh";

StringUtils.split(s, "r?");                   //[st, st, a, gh]
StringUtils.splitByWholeSeparator(s, "r?");   //[st, st, argh]

Upvotes: 2

mindas
mindas

Reputation: 26713

Use Guava Splitter:

Extracts non-overlapping substrings from an input string, typically by recognizing appearances of a separator sequence. This separator can be specified as a single character, fixed string, regular expression or CharMatcher instance. Or, instead of using a separator at all, a splitter can extract adjacent substrings of a given fixed length.

Upvotes: 3

Manuel Romeiro
Manuel Romeiro

Reputation: 1060

Using directly the Pattern class, is possible to define the expression as LITERAL, and in that case, the expression will be evaluated as is (not regex expression).

Pattern.compile(<literalExpression>, Pattern.LITERAL).split(<stringToBeSplitted>);

example:

String[] result = Pattern.compile("r?", Pattern.LITERAL).split("str?str?argh");

will result:

[st, st, argh]

Upvotes: 5

Martijn Courteaux
Martijn Courteaux

Reputation: 68857

This works perfect as well:

public static List<String> splitNonRegex(String input, String delim)
{
    List<String> l = new ArrayList<String>();
    int offset = 0;

    while (true)
    {
        int index = input.indexOf(delim, offset);
        if (index == -1)
        {
            l.add(input.substring(offset));
            return l;
        } else
        {
            l.add(input.substring(offset, index));
            offset = (index + delim.length());
        }
    }
}

Upvotes: 6

BastiS
BastiS

Reputation: 452

You can use

StringUtils.split("?r")

from commons-lang.

Upvotes: 13

贼小气
贼小气

Reputation: 49

String[] strs = str.split(Pattern.quote("r?"));

Upvotes: 4

Etienne de Martel
Etienne de Martel

Reputation: 36851

Escape the ?:

s.split("r\\?");

Upvotes: 4

Related Questions