Як розділити рядок у Java


1639

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

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

Це означає, що перший рядок буде містити символи раніше '-', а другий рядок буде містити символи після '-'. Я також хочу перевірити, чи є '-'в ньому рядок . Якщо ні, я кину виняток. Як я можу це зробити?

Відповіді:


2931

Просто використовуйте відповідний метод String#split().

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

Зауважте, що це має регулярний вираз , тому не забудьте уникнути спеціальних символів, якщо це необхідно.

є 12 символів зі спеціальними значеннями: зворотний слеш \, каретка ^, знак долара $, період або точка ., вертикальна риса або труби символ |, знак питання ?, зірочка або зірка *, знак плюс +, відкриває дужкою (, дужку ), і квадратну дужку [, що відкривається, фігурну фігурну дужку , що відкривається {, Ці спеціальні символи часто називають "метахарактеристиками".

Отже, якщо ви хочете розділити на напр. Period / крапка, .що означає " будь-який символ " в регулярному вираженні, використовуйте або зворотну косу рису,\ щоб уникнути окремого спеціального символу, як, наприклад 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
@David: 1) Це не стосується питання. 2) Це не кидає винятків. 3) ОП запитує, як розділити, а не як підрядок. 4)
Перервіться

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/… , ти маєш рацію - відповідно до більшості інших бібліотек regexp, група 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]. Вимоги не визначені настільки чіткими, якщо було б справедливо прийняти це. Рекомендую написати кілька тестів для визначення бажаної поведінки.
Michael Konietzka

Напевно, найбезпечніше змінити (result.length! = 2) на (result.length <2)
дядько Іро

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

повинен робити те, що ти хочеш. Клас струн має багато методів роботи з рядком.


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 (String regex, int limit) та NOT split (String regex) для довідкового візиту geeksforgeeks.org/split-string-java-examples
Райан Августин


16

Припускаючи, що

  • вам не потрібні регулярні вирази для вашого розколу
  • у вашому додатку ви вже використовуєте lang apache commons

Найпростіший спосіб - використовувати 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"]

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


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 (regexp) .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

Рядок розділити з декількома символами за допомогою 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(",");

Метод розділення має оптимізацію, щоб уникнути використання регулярного виразу, якщо деліметр - це один символ, а не у вищевказаному списку. В іншому випадку він повинен скласти регулярний вираз, і це не ідеально.

Використовуйте Pattern.split і попередньо компілюйте шаблон, якщо ви використовуєте складний роздільник, і ви дбаєте про продуктивність.

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

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

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

Цей останній варіант все ще створює новий Matcherоб’єкт. Ви також можете кешувати цей об'єкт і скидати його на кожен вхід для досягнення максимальної продуктивності, але це дещо складніше і не є безпечним для потоків.


7

Один із способів зробити це - пропустити String в циклі для кожного і використовувати необхідний символ розділення.

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 Sun

У такому разі перевірте 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 (регулярний вираз). Перегляньте наступні приклади:

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.