Java : List <String>을 문자열로 변환


595

자바 스크립트 Array.join()

js>["Bill","Bob","Steve"].join(" and ")
Bill and Bob and Steve

Java에는 이와 같은 것이 있습니까? StringBuilder를 사용하여 무언가를 만들 수 있다는 것을 알고 있습니다.

static public String join(List<String> list, String conjunction)
{
   StringBuilder sb = new StringBuilder();
   boolean first = true;
   for (String item : list)
   {
      if (first)
         first = false;
      else
         sb.append(conjunction);
      sb.append(item);
   }
   return sb.toString();
}

...하지만 JDK의 일부인 경우에는 그렇게 할 필요가 없습니다.



18
엄격하게 관련되어 있지는 않지만 안드로이드는 TextUtils 클래스의 일부로 내장 된 join 함수를 가지고 있습니다 : developer.android.com/reference/android/text/… , java.lang.Iterable)
Xavi

16
Java 8에는 String.join()메소드가 있습니다. Java 8 이상을 사용하는 경우이 답변을 살펴보십시오. stackoverflow.com/a/22577565/1115554
micha

답변:


763

Java 8을 사용하면 타사 라이브러리 없이이 작업을 수행 할 수 있습니다.

문자열 컬렉션에 가입하려면 새로운 String.join () 메서드를 사용할 수 있습니다 .

List<String> list = Arrays.asList("foo", "bar", "baz");
String joined = String.join(" and ", list); // "foo and bar and baz"

String 이외의 다른 유형의 Collection이있는 경우 Join Collector 와 함께 Stream API를 사용할 수 있습니다 .

List<Person> list = Arrays.asList(
  new Person("John", "Smith"),
  new Person("Anna", "Martinez"),
  new Person("Paul", "Watson ")
);

String joinedFirstNames = list.stream()
  .map(Person::getFirstName)
  .collect(Collectors.joining(", ")); // "John, Anna, Paul"

StringJoiner클래스는 유용 할 수 있습니다.


7
불행히도 String.join은 CharSequences 만 허용하며 Objects를 희망하는 것은 아닙니다. nullsafe인지 확실하지 않음
Marc

@MarcassertThat(String.join(", ", Lists.newArrayList("1", null)), is("1, null"));
이상현

StringJoiner는 [a, b, c]중괄호를 포함하는 것과 같은 것에 참여하고자 할 때 특히 유용합니다 .
koppor

@Marc String.join도 허용합니다 Iterable<CharSequence>; 인터페이스 관계 :Iterable -> Collection -> List
aff

306

Apache Commons에 대한 모든 참조는 훌륭하지만 (대부분의 사람들이 사용하는 것입니다) 구아바에 해당하는 Joiner 는 훨씬 더 좋은 API를 가지고 있다고 생각합니다 .

당신은 간단한 조인 케이스를 할 수 있습니다

Joiner.on(" and ").join(names)

또한 쉽게 null을 처리합니다.

Joiner.on(" and ").skipNulls().join(names);

또는

Joiner.on(" and ").useForNull("[unknown]").join(names);

그리고 (commons-lang보다 우선적으로 사용하는 데 관심이있는 한) 유용하게 사용할 수 있습니다.

Map<String, Integer> ages = .....;
String foo = Joiner.on(", ").withKeyValueSeparator(" is ").join(ages);
// Outputs:
// Bill is 25, Joe is 30, Betty is 35

디버깅 등에 매우 유용합니다.


10
플러그 주셔서 감사합니다! 우리의 Joiner는 Apache 라이브러리가 부족한 중간 문자열을 만들지 않고 Appendable (StringBuilder 또는 Writer와 같은)에 직접 추가 할 수있는 옵션을 제공합니다.
Kevin Bourrillion

2
이것은 훌륭하지만 .useForLastSeparator()비슷한 방법을 추가 할 수 있습니까? 이렇게하면 마지막 두 항목 사이에 "및"와 같은 것을 얻을 수 있습니다 (나머지는 ",").
Jeff Evans

2
예, 스레드 안전합니다. 결합 자에 저장된 유일한 상태는 separator(입니다 final). 구아바에서 필자가 아파치 커먼즈 (Apache Commons)에 해당하는 것을 사용했던 곳에서 보았던 모든 것은 엣지 케이스 오류와 스레드 안전성 문제가 적고 구아바에서 훨씬 더 뛰어납니다 (읽기 : 더 빠르고 안전하며 일반적으로 더 강력합니다). 더 작은 메모리 공간. 그들의 "가장 좋은 방법"안내 교장은 지금까지 사실을 지키고있는 것 같습니다.
Shadow Man

반대 방향으로 가야하는 경우 (즉, 문자열을 조각으로 분할) 구아바 클래스 스플리터를 확인하십시오-매우 잘 설계 / 구현되었습니다.
Matt Passell

Java 8에는 String.join()메소드와 StringJoiner클래스가 있습니다.
TheTechnoKid

138

기본적으로는 아니지만 많은 라이브러리가 비슷합니다.

커먼즈 랭 :

org.apache.commons.lang.StringUtils.join(list, conjunction);

봄:

org.springframework.util.StringUtils.collectionToDelimitedString(list, conjunction);

125

안드로이드 당신은 사용할 수 TextUtils의 클래스를.

TextUtils.join(" and ", names);

11
나는 이것을 찾고 있었다. 안드로이드에 최소 API 레벨 26이String.join 필요합니다 .
okarakose

49

아니요, 표준 Java API에는 그러한 편리한 방법이 없습니다.

놀랍게도 Apache Commons는 StringUtils 클래스 에서 직접 작성하고 싶지 않은 경우 이러한 기능을 제공합니다 .


11
String에는 분할이 있지만 조인이 아닌 것은 항상 나를 괴롭 혔습니다. 어떤 식 으로든 그렇게하는 것이 합리적이지만 String에는 적어도 정적 메서드가 없다는 것이 짜증납니다.
Powerlord 2013

3
나는 너와 함께있어 적어도 그들은 우리에게 준 isEmpty()방법 대신 (정적) join()의 방법 String:) : rollseyes ...
바트 Kiers

41

Java 8의 세 가지 가능성 :

List<String> list = Arrays.asList("Alice", "Bob", "Charlie")

String result = String.join(" and ", list);

result = list.stream().collect(Collectors.joining(" and "));

result = list.stream().reduce((t, u) -> t + " and " + u).orElse("");

27

Java 8 콜렉터를 사용하면 다음 코드를 사용하여 수행 할 수 있습니다.

Arrays.asList("Bill", "Bob", "Steve").stream()
.collect(Collectors.joining(" and "));

또한 Java 8에서 가장 간단한 솔루션 :

String.join(" and ", "Bill", "Bob", "Steve");

또는

String.join(" and ", Arrays.asList("Bill", "Bob", "Steve"));

21

나는 이것을 작성했다 (나는 콩과 exploit을 위해 그것을 사용 toString하지 않는다 Collection<String>) :

public static String join(Collection<?> col, String delim) {
    StringBuilder sb = new StringBuilder();
    Iterator<?> iter = col.iterator();
    if (iter.hasNext())
        sb.append(iter.next().toString());
    while (iter.hasNext()) {
        sb.append(delim);
        sb.append(iter.next().toString());
    }
    return sb.toString();
}

그러나 CollectionJSP에서 지원하지 않으므로 TLD에 대해 다음과 같이 썼습니다.

public static String join(List<?> list, String delim) {
    int len = list.size();
    if (len == 0)
        return "";
    StringBuilder sb = new StringBuilder(list.get(0).toString());
    for (int i = 1; i < len; i++) {
        sb.append(delim);
        sb.append(list.get(i).toString());
    }
    return sb.toString();
}

그리고 .tld파일에 넣으십시오 :

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
    <function>
        <name>join</name>
        <function-class>com.core.util.ReportUtil</function-class>
        <function-signature>java.lang.String join(java.util.List, java.lang.String)</function-signature>
    </function>
</taglib>

JSP 파일에서 다음과 같이 사용하십시오.

<%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%>
${funnyFmt:join(books, ", ")}

1
변경 제안 Collection<>Iterable<>?
Jason S

@JasonS +1. 좋은 지적이지만 stackoverflow.com/questions/1159797/…을
gavenkoa

19

외부 라이브러리없이 JDK를 사용하려면 원하는 코드가 올바른 방법입니다. JDK에서 사용할 수있는 간단한 "한 줄짜리"는 없습니다.

외부 라이브러리를 사용할 수 있다면 org.apache.commons.lang.StringUtils 를 살펴 보는 것이 좋습니다. Apache Commons 라이브러리의 클래스 .

사용 예 :

List<String> list = Arrays.asList("Bill", "Bob", "Steve");
String joinedResult = StringUtils.join(list, " and ");

17

그것을 달성하는 정통 방법은 새로운 기능을 정의하는 것입니다.

public static String join(String joinStr, String... strings) {
    if (strings == null || strings.length == 0) {
        return "";
    } else if (strings.length == 1) {
        return strings[0];
    } else {
        StringBuilder sb = new StringBuilder(strings.length * 1 + strings[0].length());
        sb.append(strings[0]);
        for (int i = 1; i < strings.length; i++) {
            sb.append(joinStr).append(strings[i]);
        }
        return sb.toString();
    }
}

견본:

String[] array = new String[] { "7, 7, 7", "Bill", "Bob", "Steve",
        "[Bill]", "1,2,3", "Apple ][","~,~" };

String joined;
joined = join(" and ","7, 7, 7", "Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][","~,~");
joined = join(" and ", array); // same result

System.out.println(joined);

산출:

7, 7, 7, Bill, Bob, Steve, [Bill], 1,2,3, Apple] [및 ~, ~


5
메소드 자체와 동일한 이름을 메소드 매개 변수에 제공하는 것이 가장 좋은 아이디어는 아닙니다. separator훨씬 더 암시합니다.
ccpizza

10

Java 8 솔루션 java.util.StringJoiner

Java 8에는 StringJoiner클래스가 있습니다. 그러나 여전히 자바이기 때문에 약간의 상용구를 작성해야합니다.

StringJoiner sj = new StringJoiner(" and ", "" , "");
String[] names = {"Bill", "Bob", "Steve"};
for (String name : names) {
   sj.add(name);
}
System.out.println(sj);

보다 편리한 String.join () 메소드를 사용하면 약간의 상용구를 작성할 필요가 없습니다 .
Andy Thomas

9

StringUtils 클래스와 결합 메소드가있는 아파치 공통 라이브러리를 사용할 수 있습니다.

이 링크를 확인하십시오 : https://commons.apache.org/proper/commons-lang/javadocs/api.2.0/org/apache/commons/lang/StringUtils.html

위의 링크는 시간이 지남에 따라 더 이상 사용되지 않을 수 있습니다.이 경우 웹에서 "apache commons StringUtils"를 검색하면 최신 참조를 찾을 수 있습니다.

(이 스레드에서 참조) C # String.Format () 및 String.Join ()에 해당하는 Java


7

당신은 이것을 할 수 있습니다 :

String aToString = java.util.Arrays.toString(anArray);
// Do not need to do this if you are OK with '[' and ']'
aToString = aToString.substring(1, aToString.length() - 1);

또는 한 줄짜리 ( '['및 ']'를 원하지 않는 경우에만)

String aToString = java.util.Arrays.toString(anArray).substring(1).replaceAll("\\]$", "");

도움이 되었기를 바랍니다.


1
이것은 선택의 연결을 추가하지 않습니다.
hexium

웁스 !! 미안하지만 그 점을 발견하지 못했습니다.
NawaMan

6

하나의 듀티 라인에서 순수한 JDK로 재미있는 방법 :

String[] array = new String[] { "Bill", "Bob", "Steve","[Bill]","1,2,3","Apple ][" };
String join = " and ";

String joined = Arrays.toString(array).replaceAll(", ", join)
        .replaceAll("(^\\[)|(\\]$)", "");

System.out.println(joined);

산출:

빌과 밥과 스티브와 [빌] 그리고 1,2,3와 애플] [


너무 완벽하지 않고 너무 재미없는 방법!

String[] array = new String[] { "7, 7, 7","Bill", "Bob", "Steve", "[Bill]",
        "1,2,3", "Apple ][" };
String join = " and ";

for (int i = 0; i < array.length; i++) array[i] = array[i].replaceAll(", ", "~,~");
String joined = Arrays.toString(array).replaceAll(", ", join)
        .replaceAll("(^\\[)|(\\]$)", "").replaceAll("~,~", ", ");

System.out.println(joined);

산출:

7, 7, 7, Bill, Bob, Steve, [Bill], 1,2,3, Apple] [


"[Bill]", "1,2,3"및 "Apple] ["으로 사용해보십시오. 창의적이지만 잘못된 경우가 있습니다.
Jason S

1
이제 "~, ~"로 시도하십시오. 이런 종류의 아키텍처로 완전히 방탄 프로그램을 만들 수는 없습니다.
Jason S

네, 알아요 ... 다운 보트를 제거했습니다. 그러나 여기에 답변을 게시 할 때, 특히 몇 년 전과 같은 질문에 대해서는 좀 더 신중하게 생각해야합니다. 답변은 원래 포스터에 즉시 유용 할뿐만 아니라 Google 검색에도 표시됩니다. (실제로 몇 년이 지난 질문의 경우 새로운 답변이 원래 포스터에 아무런 가치 가 없을 수도 있습니다 .) 결점이나 오류가있는 솔루션은 나중에 문맥에서 벗어난 사람들에게 해로울 수 있습니다.
Jason S

1
나는 완벽한 솔루션이 아니라 실제로 풍부한 지식과 측면 사고로 내 게시물과 같은 다른 사람들로부터 많은 것을 배웁니다. 다른 사람들을 위해 휴식을 취하십시오. 각자는 코드의 각 줄이하는 일을 이해해야합니다. 프로그래밍은 예술과 같으며 각 코드 줄조차도 프로그래머의 성격에 관한 것임을 기억하십시오. 그리고 네,이 코드를 프로덕션 환경에서 사용하지 않겠습니다!
Daniel De León


4

당신이 사용하는 경우 이클립스 컬렉션 (구 GS 컬렉션 ), 당신은 사용할 수있는 makeString()방법을.

List<String> list = Arrays.asList("Bill", "Bob", "Steve");

String string = ListAdapter.adapt(list).makeString(" and ");

Assert.assertEquals("Bill and Bob and Steve", string);

ListEclipse 콜렉션 유형으로 변환 할 수 있으면 어댑터를 제거 할 수 있습니다.

MutableList<String> list = Lists.mutable.with("Bill", "Bob", "Steve");
String string = list.makeString(" and ");

쉼표로 구분 된 문자열 만 원하면 makeString()매개 변수를 사용 하지 않는 버전을 사용할 수 있습니다 .

Assert.assertEquals(
    "Bill, Bob, Steve", 
    Lists.mutable.with("Bill", "Bob", "Steve").makeString());

노트 : 저는 Eclipse Collections의 커미터입니다.


3

Java 1.8 스트림을 사용하면

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
List<String> list = Arrays.asList("Bill","Bob","Steve").
String str = list.stream().collect(Collectors.joining(" and "));

3

편집하다

또한 toString()기본 구현 문제와 구분 기호가 포함 된 요소에 대해 알고 있지만 편집증 상태라고 생각했습니다.

그 점에 대해 두 가지 의견이 있으므로 답변을 다음과 같이 변경하고 있습니다.

static String join( List<String> list , String replacement  ) {
    StringBuilder b = new StringBuilder();
    for( String item: list ) { 
        b.append( replacement ).append( item );
    }
    return b.toString().substring( replacement.length() );
}

원래 질문과 매우 비슷합니다.

따라서 전체 항아리를 프로젝트에 추가하고 싶지 않다면 이것을 사용할 수 있습니다.

원래 코드에는 아무런 문제가 없다고 생각합니다. 실제로 모든 사람들이 제안하는 대안은 거의 동일하게 보입니다 (여러 가지 추가 검증을 수행하지만)

여기에 Apache 2.0 라이센스가 있습니다.

public static String join(Iterator iterator, String separator) {
    // handle null, zero and one elements before building a buffer
    if (iterator == null) {
        return null;
    }
    if (!iterator.hasNext()) {
        return EMPTY;
    }
    Object first = iterator.next();
    if (!iterator.hasNext()) {
        return ObjectUtils.toString(first);
    }

    // two or more elements
    StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
    if (first != null) {
        buf.append(first);
    }

    while (iterator.hasNext()) {
        if (separator != null) {
            buf.append(separator);
        }
        Object obj = iterator.next();
        if (obj != null) {
            buf.append(obj);
        }
    }
    return buf.toString();
}

이제 우리는 오픈 소스 감사합니다


이제는 작동하지만 향후 List.toString ()의 작동 방식을 확신 할 수 없습니다. 문제의 객체에 대한 정보 문자열을 인쇄하는 것 이외의 toString () 작업을 신뢰하지 않습니다. 방어에서이 솔루션을 제안하는 유일한 사람은 아닙니다.
Hans Doggen

목록의 요소 내용에 하위 문자열이 포함되어 있으면 ", "어떻게됩니까?
Bart Kiers

@Hans & @Bart : 네 말이 맞아. 나는 아무도 눈치 채지 못할 것이라고 생각했다 : P 나는 대답을 바꾸고있다.
OscarRyz

유스 케이스에 따라 다릅니다. 디버깅 목적으로 toString ()은 훌륭한 IMO입니다 ... 특정 형식에 의존하지 않는다면. 그럼에도 불구하고 코드에 대한 테스트를 작성하면 향후 변경 사항이 적용됩니다.
akostadinov

2

구글의 구아바 API는 .join ()을 가지고 있지만 (다른 답글에서 분명히 알 수 있듯이) Apache Commons는 거의 표준입니다.


1

자바 8은

Collectors.joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

메소드, 즉 널값을 사용 prefix + suffix하여 널 안전합니다.

다음과 같은 방식으로 사용할 수 있습니다.

String s = stringList.stream().collect(Collectors.joining(" and ", "prefix_", "_suffix"))

Collectors.joining(CharSequence delimiter)메소드는 joining(delimiter, "", "")내부적으로 호출합니다 .


0

Spring Framework의 StringUtils에서 이것을 사용할 수 있습니다. 이미 언급되었지만, 실제로이 코드를 가져 와서 Spring이 필요없이 즉시 작동합니다.

// from https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/util/StringUtils.java

/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
public class StringUtils {
    public static String collectionToDelimitedString(Collection<?> coll, String delim, String prefix, String suffix) {
        if(coll == null || coll.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        Iterator<?> it = coll.iterator();
        while (it.hasNext()) {
            sb.append(prefix).append(it.next()).append(suffix);
            if (it.hasNext()) {
                sb.append(delim);
            }
        }
        return sb.toString();
    }
}

-3

이 시도:

java.util.Arrays.toString(anArray).replaceAll(", ", ",")
                .replaceFirst("^\\[","").replaceFirst("\\]$","");

1
아마도 질문은 List와 Array의 사용법을 요구하기 때문에? 어깨를 으쓱
닉 Coelius

4
문자열에 ","가 있으면 작동하지 않기 때문입니다.
Cyrille Pontvieux
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.