C # String.Format () 및 String.Join ()의 Java 동등 물


111

나는 이것이 약간의 초보자 질문이라는 것을 알고 있지만 Java에서 C #의 문자열 작업과 동등한 것이 있습니까?

특히, 나는에 대해서 이야기하고 String.FormatString.Join.


따라서 String.format이 있지만 내 자신의 조인을 롤해야합니다.
Omar Kooheji

1
() 가입을 위해, 나는이 대답과 같은 : stackoverflow.com/a/6116469/562139
scorpiodawg

답변:


92

Java String 객체에는 format메소드 (1.5 기준)가 있지만 join메소드가 없습니다 .

아직 포함되지 않은 유용한 문자열 유틸리티 메소드를 얻으려면 org.apache.commons.lang.StringUtils를 사용할 수 있습니다 .


13
Google 컬렉션 : google-collections.googlecode.com에는 조이너도 있습니다.
Ron

10
Ron의 의견에 대한 참고로, google-collections는 얼마 전에 Guava로 이름이 변경되었습니다.
Kevin Bourrillion 2011 년

3
Java 8에 String.join()메서드가 도입되었음을 반영하도록이 답변을 업데이트해야합니다 .
Duncan Jones

46

String.format . 조인에 관해서는 직접 작성해야합니다.

 static String join(Collection<?> s, String delimiter) {
     StringBuilder builder = new StringBuilder();
     Iterator<?> iter = s.iterator();
     while (iter.hasNext()) {
         builder.append(iter.next());
         if (!iter.hasNext()) {
           break;                  
         }
         builder.append(delimiter);
     }
     return builder.toString();
 }

위의 출처는 http://snippets.dzone.com/posts/show/91입니다.


6
보다 정확하게 : jdk1.4 이하용 StringBuffer, jdk1.5 이하용 StringBuilder, 후자는 동기화되지 않으므로 조금 더 빠릅니다.
VonC

2
두 개의 iter.hasNext () 호출 대신 일반적으로 구분 기호를 추가 한 다음 "buf.substring (0, buf.length ()-delimeter.length ()) 반환"을 추가합니다.
Vilmantas Baranauskas

2
구분 기호를 피하기 위해 일찍 종료하여 조금 능률화 할 수 있습니다. while (true) (add_iter; if (! iter.hasNext ()) break; add_delim;}
13ren


29

Java 8 join()부터는 이제 String 클래스에서 두 개의 클래스 메소드로 사용할 수 있습니다. 두 경우 모두 첫 번째 인수는 구분 기호입니다.

개별 CharSequence을 추가 인수로 전달할 수 있습니다 .

String joined = String.join(", ", "Antimony", "Arsenic", "Aluminum", "Selenium");
// "Antimony, Arsenic, Alumninum, Selenium"

또는 다음을 전달할Iterable<? extends CharSequence> 수 있습니다 .

List<String> strings = new LinkedList<String>();
strings.add("EX");
strings.add("TER");
strings.add("MIN");
strings.add("ATE");

String joined = String.join("-", strings);
// "EX-TER-MIN-ATE"

Java 8은 또한 다음 StringJoiner과 같이 사용할 수 있는 새 클래스를 추가합니다 .

StringJoiner joiner = new StringJoiner("&");
joiner.add("x=9");
joiner.add("y=5667.7");
joiner.add("z=-33.0");

String joined = joiner.toString();
// "x=9&y=5667.7&z=-33.0"


12

다음과 같이 문자열에 변수 인수를 사용할 수도 있습니다.

  String join (String delim, String ... data) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < data.length; i++) {
      sb.append(data[i]);
      if (i >= data.length-1) {break;}
      sb.append(delim);
    }
    return sb.toString();
  }

4

조인에 관해서는 이것이 조금 덜 복잡해 보일 수 있다고 생각합니다.

public String join (Collection<String> c) {
    StringBuilder sb=new StringBuilder();
    for(String s: c)
        sb.append(s);
    return sb.toString();
}

원하는만큼 Java 5 구문을 사용하지 못하므로 (믿거 나 말거나, 최근에 1.0.x를 사용하고 있습니다) 약간 녹슬었을 수 있지만 개념은 정확하다고 확신합니다. .

편집 추가 : 문자열 추가는 느려질 수 있지만 GUI 코드 또는 일부 단기 실행 루틴으로 작업하는 경우 .005 초 또는 .006이 걸리는지 여부는 실제로 중요하지 않으므로 "joinMe"라는 컬렉션이있는 경우 기존 문자열 "target"에 추가하려는 경우 다음과 같이 인라인하는 것이 끔찍하지 않습니다.

for(String s : joinMe)
    target += s;

그것은 매우 비효율적이며 나쁜 습관이지만 수천 개의 문자열이 있거나 이것이 거대한 루프 안에 있거나 코드가 실제로 성능에 중요하지 않으면 인식 할 수있는 것은 없습니다.

더 중요한 것은 기억하기 쉽고 짧고 빠르며 매우 읽기 쉽다는 것입니다. 디자인 선택에서 성능이 항상 자동 승자가되는 것은 아닙니다.


for-loop는 정확하지만 Collection <String>으로 만들어야합니다. 그렇지 않으면 "for (Object o : c)"라고 말해야합니다. c의 모든 것이 문자열이라는 것을 보장 할 수 없기 때문입니다.
Michael Myers

좋은 점은 Generics를 사용하면 훨씬 더 녹슬 었습니다. 편집하겠습니다.
Bill K

인라인 : 문자열 + 문자열 + 문자열을 연결할 때 컴파일러는 실제로 StringBuilder를 사용하여 값을 추가합니다. for-loop 메서드에서 두 번째로 컴파일러가 동일한 작업을 수행하는지 궁금합니다.
Spencer Kormos

@Spencer K : StringBuilder를 사용하지만 각 반복마다 새로운 것을 생성합니다 (가장 효율적인 방법은 아니지만 컴파일러가 어떻게 알 수 있습니까?). JIT 컴파일러가 런타임에이를 최적화 할 수 있는지 모르겠습니다.
Michael Myers

2
오-잠깐. + =를 말하고 있습니까? 그래, 짜증나. 내 대답에 현재 루프 및 추가는 StringBuilder를 사용하며 그게 제가 말하는 것입니다. + =가 많이 향상되었지만 루프 내에서 사용하고 싶지는 않지만 버그가 많지는 않지만 쓰레기처럼 수행 할 수 있다는 점에서 (버그는 일반적으로 성능 문제에 사용되는 용어가 아닙니다. 20 년간의 프로그래밍에서). 또한 JIT는 이것을 크게 개선 할 수 있지만 저는 그것에 의존하지 않을 것입니다.
Bill K

4

여기에 아주 간단한 대답이 있습니다. +=코드가 적기 때문에 사용 하고 최적화 프로그램이이를 a로 변환하도록하십시오 StringBuilder. 이 방법을 사용하면 루프에서 "마지막"검사를 수행 할 필요가 없으며 (성능 향상) 끝에 구분 기호를 제거하는 것에 대해 걱정할 필요가 없습니다.

        Iterator<String> iter = args.iterator();
        output += iter.hasNext() ? iter.next() : "";
        while (iter.hasNext()) {
            output += "," + iter.next();
        }

1
타사 라이브러리를 포함하지 않는 매우 우아한 솔루션!
Denis Itskovich 2014

2

간단한 조인 기능을 추가하기 위해 전체 Apache 라이브러리를 가져오고 싶지 않았으므로 여기에 내 해킹이 있습니다.

    public String join(String delim, List<String> destinations) {
        StringBuilder sb = new StringBuilder();
        int delimLength = delim.length();

        for (String s: destinations) {
            sb.append(s);
            sb.append(delim);
        }

        // we have appended the delimiter to the end 
        // in the previous for-loop. Let's now remove it.
        if (sb.length() >= delimLength) {
            return sb.substring(0, sb.length() - delimLength);
        } else {
            return sb.toString();
        }
    }

@MrSnowflake 표준 문자열 작성기에 "removeCharAt (int index)"메서드가 있습니까? Im 실행중인 버전에 나타나지 않습니다.
NSjonas

@NSjonas-네 내 대답에 대한 그의 편집이 잘못되었습니다. (가) removeCharAt존재하지 않으며, 전체 기능이 더 이상 문자열을 반환 ...이 문제를 해결할 것이다.
Martin Konecny ​​2014

당신이 그것을하는 동안 ...이 현재 솔루션은 "빈 목록을 전달하면 범위를 벗어난 색인 예외"를 throw합니다.
NSjonas

delim이 1 자 이상인 경우 올바른 길이를 자르도록 편집했습니다. 당신이 정말로 필요에 따라 또한 첫 번째를 마지막 문자를 트리밍되지 않은 문제를 해결
NSjonas

피드백에 대한 Thx. 업데이트되었습니다.
Martin Konecny

1

여러 문자열을 하나로 결합 (연결)하려면 StringBuilder를 사용해야합니다. 사용하는 것보다 훨씬 낫습니다.

for(String s : joinMe)
    target += s;

StringBuilder는 동기화를 사용하지 않기 때문에 StringBuffer보다 약간의 성능 향상이 있습니다.

이와 같은 범용 유틸리티 메서드의 경우 (결국) 여러 상황에서 여러 번 호출되므로 효율적으로 만들고 많은 임시 개체를 할당하지 않아야합니다. 우리는 많은 다양한 Java 앱을 프로파일 링했으며 거의 ​​항상 문자열 연결 및 문자열 / char [] 할당이 상당한 시간 / 메모리를 차지한다는 사실을 발견했습니다.

재사용 가능한 컬렉션-> 문자열 메서드는 먼저 필요한 결과의 크기를 계산 한 다음 해당 초기 크기로 StringBuilder를 만듭니다. 이것은 문자열을 추가 할 때 사용되는 내부 char []의 불필요한 이중화 / 복사를 방지합니다.


re : 사전 계산 크기 : 작동하면 훌륭합니다. 항상 가능한 것은 아닙니다. 매번 버퍼 크기를 두 배로 늘리거나 (또는 ​​고정 요소를 실제로 곱하면) n log n 성능과 같은 결과를 얻을 수 있다는 것을 읽은 기억이납니다. 일반적인 경우 대안은 연결하려는 모든 문자열의 목록을 만드는 것입니다. ArrayList를 사용하면 (시퀀스의 길이를 미리 알지 않는 한) 다시 복사하고 LinkedList를 사용하면 노드 개체와 함께 더 많은 램과 가비지 수집을 사용합니다. 때때로 당신은 이길 수 없습니다. 시도해보세요!
Ian

위의 예제 / 문의는 결합 할 문자열의 정렬 된 컬렉션 또는 배열을 가정했습니다. 또한 크기를 미리 계산하여 내부 char [] 배열 증가로 인해 일반적으로 발생하는 사용되지 않은 추가 문자를 피할 수 있습니다.
djb

1

나는 직접 썼다.

public static String join(Collection<String> col, String delim) {
    StringBuilder sb = new StringBuilder();
    Iterator<String> 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에서 지원하지 않으므로 태그 기능에 대해 다음과 같이 썼습니다.

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



0

여기에 String.Join의 지나치게 복잡한 구현이 많이 있습니다. Java 1.8이없고 새 라이브러리를 가져 오지 않으려는 경우 아래 구현으로 충분합니다.

public String join(Collection<String> col, String delim) {
    StringBuilder sb = new StringBuilder();
    for ( String s : col ) {
        if ( sb.length() != 0 ) sb.append(delim);
        sb.append(s);
    }
    return sb.toString();
}

-1
ArrayList<Double> j=new ArrayList<>; 
j.add(1);
j.add(.92);
j.add(3); 
String ntop=j.toString(); //ntop= "[1, 0.92, 3]" 

따라서 기본적으로 String ntop은 쉼표 구분 기호와 대괄호를 사용하여 전체 컬렉션의 값을 저장합니다.


1
이 질문의 어떤 부분에 대한 답인지 잘 모르겠습니다. 문자열의 비트를 배열에 조금씩 추가 할 계획이 아니라면 String.format이 아니며 [1,0.92,3]은 일반 문자열 .join만큼 다재다능하지 않습니다.
Omar Kooheji 2013

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.