Как разбить строку в Java

1642

У меня есть строка, "004-034556"которую я хочу разделить на две строки:

string1="004";
string2="034556";

Это означает, что первая строка будет содержать символы до '-', а вторая строка будет содержать символы после '-'. Я также хочу проверить, есть ли строка '-'в нем. Если нет, я брошу исключение. Как я могу это сделать?

riyana
источник

Ответы:

2937

Просто используйте подходящий метод String#split().

String string = "004-034556";
String[] parts = string.split("-");
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556

Обратите внимание, что для этого требуется регулярное выражение , поэтому при необходимости не используйте специальные символы .

Есть 12 символов со специальным значением: обратный слеш \, каретка ^, знак доллара $, точка или точка ., символ вертикальной черты или трубы |, знак вопроса ?, звездочка или звезда *, знак плюс +, открывающая скобка (, закрывающая скобка )и открывающая квадратная скобка [, открывающаяся фигурная скобка. {Эти специальные символы часто называют «метасимволами».

Поэтому, если вы хотите разделить, например, точку / точка, .что означает « любой символ » в регулярном выражении, используйте обратную косую черту\ для экранирования отдельного специального символа, например, так split("\\.")или используйте класс символов[] для представления литеральных символов, таких как так split("[.]"), или используйте Pattern#quote()для избежать всей строки, как это split(Pattern.quote(".")).

String[] parts = string.split(Pattern.quote(".")); // Split on period.

Чтобы заранее проверить, содержит ли строка определенные символы, просто используйте String#contains().

if (string.contains("-")) {
    // Split it.
} else {
    throw new IllegalArgumentException("String " + string + " does not contain -");
}

Обратите внимание, это не требует регулярного выражения. Для этого используйте String#matches()вместо этого.

Если вы хотите сохранить разделенный символ в результирующих частях, используйте позитивный обзор . В случае, если вы хотите, чтобы символ разделения находился в левой части, используйте положительный вид сзади, добавив префикс ?<=группы к шаблону.

String string = "004-034556";
String[] parts = string.split("(?<=-)");
String part1 = parts[0]; // 004-
String part2 = parts[1]; // 034556

Если вы хотите, чтобы символ разделения находился справа, используйте положительный прогноз, добавив префикс ?=группы к шаблону.

String string = "004-034556";
String[] parts = string.split("(?=-)");
String part1 = parts[0]; // 004
String part2 = parts[1]; // -034556

Если вы хотите ограничить количество получаемых частей, вы можете указать желаемое число в качестве второго аргумента split()метода.

String string = "004-034556-42";
String[] parts = string.split("-", 2);
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556-42
BalusC
источник
27
Почему вы используете хеш-символы для разделения методов String?
Crowie
94
@Crowie: в стиле Javadoc.
BalusC
9
Угловой случай: если он не может найти, reugalr expressionон возвращает один массив элементов со всей строкой.
климат
2
Не могу поверить, что наиболее проголосовавшая версия такова. 1) part2 - это не то, что нужно автору, если исходная строка содержит два "-". 2) Нет обработки ошибок, как указано в вопросе. 3) Низкая эффективность. Поиск по одному символу требует построения и сопоставления регулярного выражения. Создан дополнительный массив и т. Д.
Дэвид
1
@ Дэвид: 1) Это не рассматривается в вопросе. 2) Это не бросает исключения. 3) ОП спрашивает, как разбивать, а не как подстроку. 4) Сделай перерыв, глубоко вдохни и выбрось все негативы из головы :)
BalusC
79

Альтернативой прямой обработке строки было бы использование регулярного выражения с группами захвата. Это имеет то преимущество, что позволяет легко вводить более сложные ограничения для ввода. Например, следующее разбивает строку на две части и гарантирует, что обе состоят только из цифр:

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");
    }
}

Поскольку в этом случае шаблон является фиксированным, его можно заранее скомпилировать и сохранить как статический член (инициализированный во время загрузки класса в примере). Регулярное выражение:

(\d+)-(\d+)

Круглые скобки обозначают группы захвата; Строка, которая соответствует этой части регулярного выражения, может быть доступна методом Match.group (), как показано. \ D соответствует и одной десятичной цифре, а + означает «соответствует одному или нескольким предыдущим выражениям.) - не имеет специального значения, поэтому просто соответствует этому символу во входных данных. Обратите внимание, что вам необходимо дважды экранировать обратную косую черту при написании этого в виде строки Java. Некоторые другие примеры:

([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
Роб Хейг
источник
Это отличное решение, однако первая часть должна быть m.group(1), вторая часть m.group(2), поскольку m.group(0)фактически возвращает шаблон полного соответствия. Я думаю, что я также помню, что group(0)раньше было первое совпадение вместо полного шаблона, возможно, это изменилось в недавнем обновлении версии Java.
ptstone
1
Спасибо. Глядя на docs.oracle.com/javase/7/docs/api/java/util/regex/… , вы правы - в соответствии с большинством других библиотек регулярных выражений, группа 0 - полное совпадение, а захваченные группы начинаются с 1. Как вы говорите, я подозреваю, что это могло измениться с тех пор, как я изначально написал ответ, но в любом случае я обновлю его, чтобы отразить текущее поведение.
Роб Хейг
42
String[] result = yourString.split("-");
if (result.length != 2) 
     throw new IllegalArgumentException("String not in correct format");

Это разделит вашу строку на 2 части. Первый элемент в массиве будет частью, содержащей материал перед -, а второй элемент в массиве будет содержать часть вашей строки после -.

Если длина массива не равна 2, то строка была не в формате: string-string.

Проверьте split()метод в Stringклассе.

https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#split-java.lang.String-int-

jjnguy
источник
5
Это примет «-555» в качестве ввода и вернет [, 555]. Требования не определены так ясно, если было бы допустимо принять это. Я рекомендую написать несколько юнит-тестов для определения желаемого поведения.
Майкл Кониецка
Вероятно, безопаснее всего изменить (result.length! = 2) на (result.length <2)
Дядя Иро
29
String[] out = string.split("-");

должен делать то, что вы хотите. У класса String есть много методов для работы со строкой.

secmask
источник
29
// This leaves the regexes issue out of question
// But we must remember that each character in the Delimiter String is treated
// like a single delimiter        

public static String[] SplitUsingTokenizer(String subject, String delimiters) {
   StringTokenizer strTkn = new StringTokenizer(subject, delimiters);
   ArrayList<String> arrLis = new ArrayList<String>(subject.length());

   while(strTkn.hasMoreTokens())
      arrLis.add(strTkn.nextToken());

   return arrLis.toArray(new String[0]);
}
Mnyikka
источник
60
В JavaDoc четко сказано: « StringTokenizerэто устаревший класс, который сохраняется из соображений совместимости, хотя его использование не рекомендуется в новом коде . Рекомендуется всем, кто ищет эту функциональность, вместо этого использовать splitметод Stringили java.util.regexпакет».
Bvdb
23

С Java 8:

    List<String> stringList = Pattern.compile("-")
            .splitAsStream("004-034556")
            .collect(Collectors.toList());

    stringList.forEach(s -> System.out.println(s));
Сомайя Кумбера
источник
2
Если вы хотите удалить пробелы, добавьте .map(String::trim)послеsplit
Roland
18

Требования оставили место для интерпретации. Я рекомендую написать метод,

public final static String[] mySplit(final String s)

которые инкапсулируют эту функцию. Конечно, вы можете использовать String.split (..), как указано в других ответах для реализации.

Вы должны написать несколько юнит-тестов для входных строк и желаемых результатов и поведения.

Хорошие тестовые кандидаты должны включать в себя:

 - "0022-3333"
 - "-"
 - "5555-"
 - "-333"
 - "3344-"
 - "--"
 - ""
 - "553535"
 - "333-333-33"
 - "222--222"
 - "222--"
 - "--4555"

Определив соответствующие результаты теста, вы можете указать поведение.

Например, если "-333"должен вернуться [,333]или если это ошибка. Можно "333-333-33"разделить на [333,333-33] or [333-333,33]или это ошибка? И так далее.

Михаил Кониецка
источник
4
Полезный совет, но на самом деле не ответ на вопрос. Если вы поддерживаете другой ответ с деталями, то комментарий предпочтителен.
Крис Маунтфорд
Используйте: split (строковое регулярное выражение, int limit) и NOT split ( строковое
Райан Августин
16

Вы можете попробовать так же

 String concatenated_String="hi^Hello";

 String split_string_array[]=concatenated_String.split("\\^");
ШУНМУГА РАДЖ ПРАБАКАРАН
источник
16

При условии, что

  • вам не нужны регулярные выражения для вашего раскола
  • вы уже используете Apache Commons Lang в вашем приложении

Самый простой способ - использовать StringUtils # split (java.lang.String, char) . Это удобнее, чем тот, который предоставляется Java из коробки, если вам не нужны регулярные выражения. Как сказано в его руководстве, он работает так:

A null input String returns null.

 StringUtils.split(null, *)         = null
 StringUtils.split("", *)           = []
 StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
 StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
 StringUtils.split("a:b:c", '.')    = ["a:b:c"]
 StringUtils.split("a b c", ' ')    = ["a", "b", "c"]

Я бы порекомендовал использовать commong-lang, поскольку обычно он содержит много полезного. Однако, если вам это не нужно для чего-то еще, кроме деления, тогда лучше реализовать себя или экранировать регулярное выражение.

эйс
источник
15

Используйте метод разделения org.apache.commons.lang.StringUtils, который может разбивать строки на основе символа или строки, которую вы хотите разделить.

Подпись метода:

public static String[] split(String str, char separatorChar);

В вашем случае вы хотите разбить строку, когда есть «-».

Вы можете просто сделать следующее:

String str = "004-034556";

String split[] = StringUtils.split(str,"-");

Вывод:

004
034556

Предположим, что если -в вашей строке не существует, он возвращает заданную строку, и вы не получите никакого исключения.

Сандип Ванама
источник
14

Подводя итог: есть как минимум пять способов разбить строку в Java:

  1. String.split ():

    String[] parts ="10,20".split(",");
  2. Pattern.compile (регулярное выражение) .splitAsStream (вход):

    List<String> strings = Pattern.compile("\\|")
          .splitAsStream("010|020202")
          .collect(Collectors.toList());
  3. StringTokenizer (устаревший класс):

    StringTokenizer strings = new StringTokenizer("Welcome to EXPLAINJAVA.COM!", ".");
    while(strings.hasMoreTokens()){
        String substring = strings.nextToken();
        System.out.println(substring);
    }
  4. Google Guava Splitter:

    Iterable<String> result = Splitter.on(",").split("1,2,3,4");
  5. Apache Commons StringUtils:

    String[] strings = StringUtils.split("1,2,3,4", ",");

Таким образом, вы можете выбрать лучший вариант для вас, в зависимости от того, что вам нужно, например, тип возвращаемого значения (массив, список или итерируемый).

Вот большой обзор этих методов и наиболее распространенных примеров (как разделить на точки, косая черта, знак вопроса и т. Д.)

Дмитрий Швечиков
источник
13

Самый быстрый способ, который также потребляет наименьшее количество ресурсов, может быть:

String s = "abc-def";
int p = s.indexOf('-');
if (p >= 0) {
    String left = s.substring(0, p);
    String right = s.substring(p + 1);
} else {
  // s does not contain '-'
}
Дэвид
источник
6
Самым дефицитным ресурсом часто являются время и внимание программиста. Этот код потребляет больше этого ресурса, чем альтернативы.
Крис Маунтфорд
у вас есть много встроенных ресурсов, которые вы можете использовать, где производительность действительно считается, этому решению не хватает времени выполнения производительности
J Sanchez
1
Чтобы сделать простое разбиение на один символ с проверкой ошибок, это не сложнее, чем версия регулярного выражения.
tekHedd
Браво! Наконец ответ на этот вопрос, который не использует регулярные выражения! Использование регулярных выражений для этой простой задачи - довольно сложная задача.
Габриэль Магана
Существует только одно «-», требуется исключение, и результат должен идти к string1 и string2. Сделай string1 = s.substring(0, s.indexOf("-")); string2 = s.substring(s.indexOf("-") + 1);из этого. Вы получите StringIndexOutOfBoundsExceptionавтоматически, если не было "-".
Каплан
13

String Split с несколькими символами с использованием Regex

public class StringSplitTest {
     public static void main(String args[]) {
        String s = " ;String; String; String; String, String; String;;String;String; String; String; ;String;String;String;String";
        //String[] strs = s.split("[,\\s\\;]");
        String[] strs = s.split("[,\\;]");
        System.out.println("Substrings length:"+strs.length);
        for (int i=0; i < strs.length; i++) {
            System.out.println("Str["+i+"]:"+strs[i]);
        }
     }
  }

Вывод:

Substrings length:17
Str[0]:
Str[1]:String
Str[2]: String
Str[3]: String
Str[4]: String
Str[5]: String
Str[6]: String
Str[7]:
Str[8]:String
Str[9]:String
Str[10]: String
Str[11]: String
Str[12]:
Str[13]:String
Str[14]:String
Str[15]:String
Str[16]:String

Но не ожидайте одинакового вывода во всех версиях JDK. Я видел одну ошибку, которая существует в некоторых версиях JDK, где первая пустая строка была проигнорирована. Эта ошибка отсутствует в последней версии JDK, но существует в некоторых версиях между поздними версиями JDK 1.7 и ранними версиями 1.8.

Равиндра Бабу
источник
13

Для простых случаев использования String.split()следует делать работу. Если вы используете guava, есть также класс Splitter, который позволяет связывать различные строковые операции и поддерживает CharMatcher :

Splitter.on('-')
       .trimResults()
       .omitEmptyStrings()
       .split(string);
Виталий Федоренко
источник
10
public class SplitTest {

    public static String[] split(String text, String delimiter) {
        java.util.List<String> parts = new java.util.ArrayList<String>();

        text += delimiter;

        for (int i = text.indexOf(delimiter), j=0; i != -1;) {
            String temp = text.substring(j,i);
            if(temp.trim().length() != 0) {
                parts.add(temp);
            }
            j = i + delimiter.length();
            i = text.indexOf(delimiter,j);
        }

        return parts.toArray(new String[0]);
    }


    public static void main(String[] args) {
        String str = "004-034556";
        String delimiter = "-";
        String result[] = split(str, delimiter);
        for(String s:result)
            System.out.println(s);
    }
}
Ахилеш Дхар Дубей
источник
9

Вы можете разбить строку на разрыв строки, используя следующую инструкцию:

String textStr[] = yourString.split("\\r?\\n");

Вы можете разбить строку на дефис / символ, используя следующую инструкцию:

String textStr[] = yourString.split("-");
RajeshVijayakumar
источник
9
import java.io.*;

public class BreakString {

  public static void main(String args[]) {

    String string = "004-034556-1234-2341";
    String[] parts = string.split("-");

    for(int i=0;i<parts.length;i++) 
      System.out.println(parts[i]);
    }
  }
}
Рави Пандей
источник
4
если я могу поделиться советом, как ваш ответ приносит больше пользы, чем уже принятое решение? stackoverflow.com/a/3481842/420096 В таких ситуациях вы можете проголосовать за существующее решение, особенно если это явный тривиальный случай, подобный этому.
Сомбрикс
8

Вы можете использовать Split ():

import java.io.*;

public class Splitting
{

    public static void main(String args[])
    {
        String Str = new String("004-034556");
        String[] SplittoArray = Str.split("-");
        String string1 = SplittoArray[0];
        String string2 = SplittoArray[1];
    }
}

Иначе, вы можете использовать StringTokenizer:

import java.util.*;
public class Splitting
{
    public static void main(String[] args)
    {
        StringTokenizer Str = new StringTokenizer("004-034556");
        String string1 = Str.nextToken("-");
        String string2 = Str.nextToken("-");
    }
}
Сарат Чандра
источник
8

Есть только два метода, которые вы действительно должны рассмотреть.

Используйте String.split для односимвольного разделителя, или вы не заботитесь о производительности

Если производительность не является проблемой или если разделитель представляет собой один символ, который не является специальным символом регулярного выражения (т. Е. Не одним из них .$|()[{^?*+\), то вы можете использовать его String.split.

String[] results = input.split(",");

Метод split имеет оптимизацию, позволяющую избежать использования регулярного выражения, если разделитель представляет собой один символ и отсутствует в приведенном выше списке. В противном случае он должен скомпилировать регулярное выражение, и это не идеально.

Используйте Pattern.split и прекомпилируйте шаблон, если используете сложный разделитель, и вы заботитесь о производительности.

Если производительность является проблемой, и ваш разделитель не является одним из вышеперечисленных, вы должны предварительно скомпилировать шаблон регулярного выражения, который затем можно использовать повторно.

// Save this somewhere
Pattern pattern = Pattern.compile("[,;:]");

/// ... later
String[] results = pattern.split(input);

Этот последний вариант все еще создает новый Matcherобъект. Вы также можете кэшировать этот объект и сбрасывать его для каждого входа для максимальной производительности, но это несколько сложнее и не поточнобезопасно.

rghome
источник
7

Один из способов сделать это - запустить строку в цикле for-each и использовать необходимый символ разделения.

public class StringSplitTest {

    public static void main(String[] arg){
        String str = "004-034556";
        String split[] = str.split("-");
        System.out.println("The split parts of the String are");
        for(String s:split)
        System.out.println(s);
    }
}

Вывод:

The split parts of the String are:
004
034556
Кешав Прадип Раманатх
источник
7

Пожалуйста, не используйте класс StringTokenizer, так как это унаследованный класс, который сохраняется из соображений совместимости, и его использование не рекомендуется в новом коде. И мы можем использовать метод разделения, как предложено другими.

String[] sampleTokens = "004-034556".split("-");
System.out.println(Arrays.toString(sampleTokens));

И, как ожидается, он напечатает:

[004, 034556]

В этом ответе я также хочу указать на одно изменение, которое произошло с splitметодом в Java 8 . Метод String # split () использует Pattern.split, и теперь он удалит пустые строки в начале массива результатов. Обратите внимание на это изменение в документации для Java 8:

Когда в начале входной последовательности есть совпадение положительной ширины, тогда пустая ведущая подстрока включается в начало результирующего массива. Однако совпадение с нулевой шириной в начале никогда не приводит к такой пустой ведущей подстроке

Это означает для следующего примера:

String[] sampleTokensAgain = "004".split("");
System.out.println(Arrays.toString(sampleTokensAgain));

мы получим три строки: [0, 0, 4]а не четыре, как это было в Java 7 и ранее. Также проверьте этот похожий вопрос .

akhil_mittal
источник
7

Вот два способа достижения этого двумя.

ПУТЬ 1: Поскольку вам нужно разделить два числа специальным символом, вы можете использовать регулярное выражение

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TrialClass
{
    public static void main(String[] args)
    {
        Pattern p = Pattern.compile("[0-9]+");
        Matcher m = p.matcher("004-034556");

        while(m.find())
        {
            System.out.println(m.group());
        }
    }
}

ПУТЬ 2: Использование метода разделения строк

public class TrialClass
{
    public static void main(String[] args)
    {
        String temp = "004-034556";
        String [] arrString = temp.split("-");
        for(String splitString:arrString)
        {
            System.out.println(splitString);
        }
    }
}
Акшай Гайквад
источник
6

Вы можете просто использовать StringTokenizer, чтобы разделить строку на две или более частей, независимо от того, существуют ли какие-либо разделители:

StringTokenizer st = new StringTokenizer("004-034556", "-");
while(st.hasMoreTokens())
{
    System.out.println(st.nextToken());
}
Рохит-Пандей
источник
4

Проверьте split()метод в Stringклассе на Javadoc.

https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split(java.lang.String)

String data = "004-034556-1212-232-232";
int cnt = 1;
for (String item : data.split("-")) {
        System.out.println("string "+cnt+" = "+item);
        cnt++;
}

Здесь много примеров разбитой строки, но я немного оптимизировал код.

Дивьеш Канзария
источник
Замените -на |и посмотрите, что получится :)
R Вс
В этом случае, проверьте stackoverflow.com/questions/10796160/…
R Вс
4
String str="004-034556"
String[] sTemp=str.split("-");// '-' is a delimiter

string1=004 // sTemp[0];
string2=034556//sTemp[1];
Шива
источник
3

Я просто хотел написать алгоритм вместо использования встроенных функций Java:

public static List<String> split(String str, char c){
    List<String> list = new ArrayList<>();
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < str.length(); i++){
        if(str.charAt(i) != c){
            sb.append(str.charAt(i));
        }
        else{
            if(sb.length() > 0){
                list.add(sb.toString());
                sb = new StringBuilder();
            }
        }
    }

    if(sb.length() >0){
        list.add(sb.toString());
    }
    return list;
}
Никто
источник
1

Вы можете использовать метод split:

public class Demo {
    public static void main(String args[]) {
        String str = "004-034556";

        if ((str.contains("-"))) {
            String[] temp = str.split("-");
            for (String part:temp) {
                System.out.println(part);
            }
        }
        else {
            System.out.println(str + " does not contain \"-\".");
        }
    }
}
Jamith
источник
1

Чтобы разбить строку, используется String.split (regex). Просмотрите следующие примеры:

String data = "004-034556";
String[] output = data.split("-");
System.out.println(output[0]);
System.out.println(output[1]);

Вывод

004
034556

Замечания:

Это разделение (регулярное выражение) принимает регулярное выражение в качестве аргумента. Не забудьте экранировать специальные символы регулярного выражения, такие как точка / точка.

КИБУ Хасан
источник
0
String s="004-034556";
for(int i=0;i<s.length();i++)
{
    if(s.charAt(i)=='-')
    {
        System.out.println(s.substring(0,i));
        System.out.println(s.substring(i+1));
    }
}

Как уже упоминалось, split () - лучший вариант, который может быть использован в вашем случае. Альтернативным методом может быть использование substring ().

Сэм младший
источник
0

Чтобы разбить строку, используйте String.split(regex):

String phone = "004-034556";
String[] output = phone.split("-");
System.out.println(output[0]);
System.out.println(output[1]);

Вывод:

004
034556
КИБУ Хасан
источник