Если вы используете .split(delim) в строке, которая начинается с разделителя, результирующий массив начнется с пустой строки. Вот пример:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String[] s = " aaa bbb ccc ".split("[^\\w]+");
System.out.println(Arrays.toString(s));
}
}
результат:
[, aaa, bbb, ccc]
Хотя я ожидал, что это будет
[aaa, bbb, ccc]
Так работает этот метод, и нет способа заставить его работать так, как я хотел...
Да, это особенность, а не ошибка. По определению между элементами стоит разделитель. Если ваш ввод начинается с разделителя, это означает, что первый элемент отсутствует. Пустой объект String — это подходящий способ в Java представить отсутствующий текст, либо он, либо null.




Используйте метод String.trim() перед разделением()
К сожалению, это применимо только в приведенном мной примере. На самом деле, мне тоже нужно что-то вроде ". aaa bbb ccc", чтобы стать [aaa,bbb,ccc].
На самом деле, мне нужно что-то вроде «. aaa bbb ccc», чтобы также стать [aaa,bbb,ccc]. Это просто звучит как неверный ввод/плохой синтаксический анализ. Почему бы и нет [., aaa, bbb, ccc]? Если это действительно так, похоже, вы вообще не хотите String::split
Вы можете использовать (?i)[a-z0-9_]+:
(?i) — это нечувствительный флаг, который игнорирует и ослабляет чувствительность к регистру (например, apple, Apple и APPLE обрабатываются одинаково).[a-z0-9_]: разрешен ли список символов, и вы можете его изменить, если хотите. (Примечание: A-Za-z0-9_ и \w одинаковы.)import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Solution {
public static void main(String[] args) {
final String regex = "(?i)[a-z0-9_]+";
final String string = " aaa bbb ccc \n"
+ "aaa bbb \n"
+ " ccc 12aaa _bbb 1_ccc hhh ";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
System.out.println("Full match: " + matcher.group(0));
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println("Group " + i + ": " + matcher.group(i));
}
}
}
}
Full match: aaa
Full match: bbb
Full match: ccc
Full match: aaa
Full match: bbb
Full match: ccc
Full match: 12aaa
Full match: _bbb
Full match: 1_ccc
Full match: hhh
Вы также можете сохранить матчи в ArrayList():
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.List;
public class Solution {
public static void main(String[] args) {
final String regex = "(?i)[a-z0-9_]+";
final String string = " aaa bbb ccc \n"
+ "aaa bbb \n"
+ " ccc 12aaa _bbb 1_ccc hhh ";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);
List<String> matches = new ArrayList<>();
while (matcher.find()) {
matches.add(matcher.group(0));
}
for (String match : matches) {
System.out.println(match);
}
}
}
aaa
bbb
ccc
aaa
bbb
ccc
12aaa
_bbb
1_ccc
hhh
Вы также можете использовать split():
import java.util.ArrayList;
import java.util.List;
public class Solution {
public static void main(String[] args) {
final String string = " aaa bbb ccc \n"
+ "aaa bbb \n"
+ " ccc 12aaa _bbb 1_ccc hhh ";
final String regex = "\\s+";
String[] parts = string.split(regex);
List<String> matches = new ArrayList<>();
for (String part : parts) {
if (!part.isEmpty()) {
matches.add(part);
}
}
for (String match : matches) {
System.out.println(match);
}
}
}
Так что на самом деле правильным ответом было бы использовать Matcher и Pattern для разделения строки вместо метода .split()...
@AndreyVoeyko Это один из способов сделать это. Временная сложность равна O(N). Вы также можете использовать String[] parts = string.split(regex);.
Если вам интересно, вот потоковое решение. Этот конкретный соответствует всему, что не имеет пробелов.
[\\S]+ — класс символов, состоящий из одного или нескольких символов без пробелов.String str = " aaa Foo bbb ccc ab123d _aksks_ ";
String[] result = Pattern.compile("[\\S]+").matcher(str).results()
.map(MatchResult::group).toArray(String[]::new);
System.out.println(Arrays.toString(result));
принты
[aaa, Foo, bbb, ccc, ab123d, _aksks_]
Вы можете управлять разделителем, изменяя класс символов в регулярном выражении. Итак, если строка разделена сочетанием пробелов и запятых, вы можете использовать [^\\s,]+. В котором говорится, что совпадение соответствует всему, кроме пробелов и запятых.
Всегда читайте Javadoc: «Когда в начале этой строки есть совпадение положительной ширины, в начало результирующего массива включается пустая ведущая подстрока. Однако совпадение с нулевой шириной в начале никогда не создает такую пустую ведущую подстроку». ." Ответ @DCurtis - одно из возможных решений.