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


1642

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

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

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

Ответы:


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

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-


5
Это примет «-555» в качестве ввода и вернет [, 555]. Требования не определены так ясно, если было бы допустимо принять это. Я рекомендую написать несколько юнит-тестов для определения желаемого поведения.
Майкл Кониецка

Вероятно, безопаснее всего изменить (result.length! = 2) на (result.length <2)
Дядя Иро

29
String[] out = string.split("-");

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


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

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

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

  • вам не нужны регулярные выражения для вашего раскола
  • вы уже используете 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("-");

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объект. Вы также можете кэшировать этот объект и сбрасывать его для каждого входа для максимальной производительности, но это несколько сложнее и не поточнобезопасно.


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 и ранее. Также проверьте этот похожий вопрос .


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

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.