Use the appropriately named method String#split().
String string = "004-034556";
String[] parts = string.split("-");
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556
Note that split's argument is assumed to be a regular expression, so remember to escape special characters if necessary.
there are 12 characters with special meanings: the backslash
\, the caret^, the dollar sign$, the period or dot., the vertical bar or pipe symbol|, the question mark?, the asterisk or star*, the plus sign+, the opening parenthesis(, the closing parenthesis), and the opening square bracket[, the opening curly brace{, These special characters are often called "metacharacters".
For instance, to split on a period/dot . (which means "any character" in regex), use either backslash \ to escape the individual special character like so split("\\."), or use character class [] to represent literal character(s) like so split("[.]"), or use Pattern#quote() to escape the entire string like so split(Pattern.quote(".")).
String[] parts = string.split(Pattern.quote(".")); // Split on the exact string.
To test beforehand if the string contains certain character(s), just use String#contains().
if (string.contains("-")) {
// Split it.
} else {
throw new IllegalArgumentException("String " + string + " does not contain -");
}
Note, this does not take a regular expression. For that, use String#matches() instead.
If you'd like to retain the split character in the resulting parts, then make use of positive lookaround. In case you want to have the split character to end up in left hand side, use positive lookbehind by prefixing ?<= group on the pattern.
String string = "004-034556";
String[] parts = string.split("(?<=-)");
String part1 = parts[0]; // 004-
String part2 = parts[1]; // 034556
In case you want to have the split character to end up in right hand side, use positive lookahead by prefixing ?= group on the pattern.
String string = "004-034556";
String[] parts = string.split("(?=-)");
String part1 = parts[0]; // 004
String part2 = parts[1]; // -034556
If you'd like to limit the number of resulting parts, then you can supply the desired number as 2nd argument of split() method.
String string = "004-034556-42";
String[] parts = string.split("-", 2);
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556-42
Answer from BalusC on Stack OverflowUse the appropriately named method String#split().
String string = "004-034556";
String[] parts = string.split("-");
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556
Note that split's argument is assumed to be a regular expression, so remember to escape special characters if necessary.
there are 12 characters with special meanings: the backslash
\, the caret^, the dollar sign$, the period or dot., the vertical bar or pipe symbol|, the question mark?, the asterisk or star*, the plus sign+, the opening parenthesis(, the closing parenthesis), and the opening square bracket[, the opening curly brace{, These special characters are often called "metacharacters".
For instance, to split on a period/dot . (which means "any character" in regex), use either backslash \ to escape the individual special character like so split("\\."), or use character class [] to represent literal character(s) like so split("[.]"), or use Pattern#quote() to escape the entire string like so split(Pattern.quote(".")).
String[] parts = string.split(Pattern.quote(".")); // Split on the exact string.
To test beforehand if the string contains certain character(s), just use String#contains().
if (string.contains("-")) {
// Split it.
} else {
throw new IllegalArgumentException("String " + string + " does not contain -");
}
Note, this does not take a regular expression. For that, use String#matches() instead.
If you'd like to retain the split character in the resulting parts, then make use of positive lookaround. In case you want to have the split character to end up in left hand side, use positive lookbehind by prefixing ?<= group on the pattern.
String string = "004-034556";
String[] parts = string.split("(?<=-)");
String part1 = parts[0]; // 004-
String part2 = parts[1]; // 034556
In case you want to have the split character to end up in right hand side, use positive lookahead by prefixing ?= group on the pattern.
String string = "004-034556";
String[] parts = string.split("(?=-)");
String part1 = parts[0]; // 004
String part2 = parts[1]; // -034556
If you'd like to limit the number of resulting parts, then you can supply the desired number as 2nd argument of split() method.
String string = "004-034556-42";
String[] parts = string.split("-", 2);
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556-42
An alternative to processing the string directly would be to use a regular expression with capturing groups. This has the advantage that it makes it straightforward to imply more sophisticated constraints on the input. For example, the following splits the string into two parts, and ensures that both consist only of digits:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class SplitExample
{
private static Pattern twopart = Pattern.compile("(\\d+)-(\\d+)");
public static void checkString(String s)
{
Matcher m = twopart.matcher(s);
if (m.matches()) {
System.out.println(s + " matches; first part is " + m.group(1) +
", second part is " + m.group(2) + ".");
} else {
System.out.println(s + " does not match.");
}
}
public static void main(String[] args) {
checkString("123-4567");
checkString("foo-bar");
checkString("123-");
checkString("-4567");
checkString("123-4567-890");
}
}
As the pattern is fixed in this instance, it can be compiled in advance and stored as a static member (initialised at class load time in the example). The regular expression is:
(\d+)-(\d+)
The parentheses denote the capturing groups; the string that matched that part of the regexp can be accessed by the Match.group() method, as shown. The \d matches and single decimal digit, and the + means "match one or more of the previous expression). The - has no special meaning, so just matches that character in the input. Note that you need to double-escape the backslashes when writing this as a Java string. Some other examples:
([A-Z]+)-([A-Z]+) // Each part consists of only capital letters
([^-]+)-([^-]+) // Each part consists of characters other than -
([A-Z]{2})-(\d+) // The first part is exactly two capital letters,
// the second consists of digits
algorithm - Split string by character in Java - Code Review Stack Exchange
java - Split string into array of character strings - Stack Overflow
Split String every nth char / or the first occurrence of a period
Split a string with multiple delimiters
Erm, you can just put all of the delimiters you want in the quotes for the string passed to .split()
[PS] C:\Users\> $string = "part1.part2;part3"
[PS] C:\Users\> $string.split(".;")
part1
part2
part3 More on reddit.com Videos
Sloppiness
There are several careless mistakes that are easy to fix.
Don't use implementation types in declaration, unless you really need to use a specific feature of that implementation:
ArrayList<String> arr = new ArrayList<String>();
Use the interface type instead:
List<String> arr = new ArrayList<String>();
Instead of creating a new StringBuilder, it might be faster to reset it, like this:
sb.setLength(0);
See this discussion for more details.
Don't convert a List to an array like this:
return arr.toArray(new String[0]);
It's recommended to pass a correctly sized array:
return arr.toArray(new String[arr.size()]);
Better unit tests
Give your test cases meaningful names. So that when your IDE reports some of them failing, it will be easier to understand what failed. For example:
@Test
public void testNormalSentence() {
final String str1 = "Because";
final String str2 = "I'm";
final String str3 = "Batman";
final char delim = ' ';
String[] parts = StringUtility.split(str1 + delim + str2 + delim + str3, delim);
Assert.assertEquals(Arrays.asList(str1, str2, str3), Arrays.asList(parts));
}
@Test
public void testStartingWithDelim() {
final String str1 = "";
final String str2 = "I'm";
final String str3 = "Batman";
final char delim = ' ';
String[] parts = StringUtility.split(str1 + delim + str2 + delim + str3, delim);
Assert.assertEquals(Arrays.asList(str1, str2, str3), Arrays.asList(parts));
}
@Test
public void testEmptyString() {
final String str1 = "";
final char delim = ' ';
String[] parts = StringUtility.split(str1, delim);
Assert.assertEquals(Arrays.asList(str1), Arrays.asList(parts));
}
These new names describe well exactly what they are testing. This should help understanding the code.
The assertions can be simplified, instead of:
String[] parts = StringUtility.split(str1 + delim + str2 + delim + str3, delim); Assert.assertTrue(parts.length == 3); Assert.assertTrue(parts[0].equals(str1)); Assert.assertTrue(parts[1].equals(str2)); Assert.assertTrue(parts[2].equals(str3));
You could simplify like this:
String[] parts = StringUtility.split(str1 + delim + str2 + delim + str3, delim);
Assert.assertEquals(Arrays.asList(str1, str2, str3), Arrays.asList(parts));
This is exactly the same, but shorter, and a lot easier to write.
I would add some more test cases:
@Test
public void testOnlyDelim() {
final String str1 = "";
final char delim = ' ';
String[] parts = StringUtility.split("" + delim + delim, delim);
Assert.assertEquals(Arrays.asList(str1, str1, str1), Arrays.asList(parts));
}
@Test
public void testNotContainingDelim() {
final String str1 = "hello";
final char delim = 'x';
String[] parts = StringUtility.split(str1, delim);
Assert.assertEquals(Arrays.asList(str1), Arrays.asList(parts));
}
Suggested implementation
@heslacher's implementation is very close to my taste. Here's a variation of that, with some minor changes:
public static String[] split(String strToSplit, char delimiter) {
List<String> arr = new ArrayList<>();
int foundPosition;
int startIndex = 0;
while ((foundPosition = strToSplit.indexOf(delimiter, startIndex)) > -1) {
arr.add(strToSplit.substring(startIndex, foundPosition));
startIndex = foundPosition + 1;
}
arr.add(strToSplit.substring(startIndex));
return arr.toArray(new String[arr.size()]);
}
The first thought that came to my mind has been why creating always a new StringBuilder after the delimiter is found. So I changed this and called the setLength() with zero as parameter like
public static String[] split(String strToSplit, char delimiter) {
ArrayList<String> arr = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < strToSplit.length(); i++) {
char at = strToSplit.charAt(i);
if (at == delimiter) {
arr.add(sb.toString());
sb.setLength(0);
} else {
sb.append(at);
}
}
arr.add(sb.toString());
return arr.toArray(new String[0]);
}
The next I thought, why use a StringBuilder and the CharAt(), if a indexOf() could be used, so I changed it to
public static String[] split(String strToSplit, char delimiter) {
ArrayList<String> arr = new ArrayList<String>();
int foundPosition = 0;
int startIndex = 0;
while ((foundPosition = strToSplit.indexOf(delimiter, startIndex)) >= 0) {
arr.add(strToSplit.substring(startIndex, foundPosition));
startIndex = foundPosition + 1;
}
arr.add(strToSplit.substring(startIndex));
return arr.toArray(new String[0]);
}
You need to profile it by yourself.