IT story

문자열 객체 목록을 연결하는 가장 좋은 방법은 무엇입니까?

hot-time 2020. 6. 20. 09:34
반응형

문자열 객체 목록을 연결하는 가장 좋은 방법은 무엇입니까? [복제]


이 질문에는 이미 답변이 있습니다.

String 객체 목록을 연결하는 가장 좋은 방법은 무엇입니까? 나는 이런 식으로 생각하고 있습니다.

List<String> sList = new ArrayList<String>();

// add elements

if (sList != null)
{
    String listString = sList.toString();
    listString = listString.subString(1, listString.length() - 1);
}

어떻게 든 이것이 StringBuilder / StringBuffer 접근 방식을 사용하는 것보다 더 깔끔하다는 것을 알았습니다.

생각이나 의견이 있습니까?


귀하의 접근 방식은 Java의 ArrayList # toString () 구현에 따라 다릅니다.

구현이 Java API에 문서화되어 있으며 변경 될 가능성은 거의 없지만 가능할 수 있습니다. 이것을 직접 구현하는 것이 훨씬 안정적입니다 (루프, StringBuilders, 원하는대로 재귀).

물론이 접근법은 "더 낮거나"너무 "달콤하다"또는 "돈"처럼 보일 수 있지만, 제 생각에는 더 나쁜 접근법입니다.


Apache Commons Lang에서 StringUtils.join 메소드 중 하나를 사용하십시오 .

import org.apache.commons.lang3.StringUtils;

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

Java 8을 사용하기에 운이 좋으면 String.join을 사용하는 것이 더 쉽습니다.

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

Java 8 이상 사용

String str = list.stream().collect(Collectors.joining())

또는

String str = String.join("", list);

코드 핀 답변의 변형

public static String concatStringsWSep(Iterable<String> strings, String separator) {
    StringBuilder sb = new StringBuilder();
    String sep = "";
    for(String s: strings) {
        sb.append(sep).append(s);
        sep = separator;
    }
    return sb.toString();                           
}

Android 용으로 개발중인 경우 TextUtils.joinSDK 제공합니다.


이것은 내가 지금까지 찾은 가장 우아하고 깨끗한 방법입니다.

list.stream().collect(Collectors.joining(delimiter));

구아바 는 Google의 깔끔한 라이브러리입니다.

Joiner joiner = Joiner.on(", ");
joiner.join(sList);

Java 8에서 String.join (list)을 선호합니다.


이 코딩 호러 블로그 항목을 보셨습니까?

마이크로 최적화 극장의 슬픈 비극

나는 그것이 "더 가까운"것인지 아닌지는 확실하지 않지만, 성능 관점에서 보면 그다지 중요하지 않을 것입니다.


StringBuilder가 빠르고 효율적일 것 같습니다.

기본 형식은 다음과 같습니다.

public static String concatStrings(List<String> strings)
{
    StringBuilder sb = new StringBuilder();
    for(String s: strings)
    {
        sb.append(s);
    }
    return sb.toString();       
}

If that's too simplistic (and it probably is), you can use a similar approach and add a separator like this:

    public static String concatStringsWSep(List<String> strings, String separator)
{
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < strings.size(); i++)
    {
        sb.append(strings.get(i));
        if(i < strings.size() - 1)
            sb.append(separator);
    }
    return sb.toString();               
}

I agree with the others who have responded to this question when they say that you should not rely on the toString() method of Java's ArrayList.


I somehow found this to be neater than using the StringBuilder/StringBuffer approach.

I guess it depends on what approach you took.

The AbstractCollection#toString() method simply iterates over all the elements and appends them to a StringBuilder. So your method may be saving a few lines of code but at the cost of extra String manipulation. Whether that tradeoff is a good one is up to you.


ArrayList inherits its toString()-method from AbstractCollection, ie:

public String toString() {
    Iterator<E> i = iterator();
    if (! i.hasNext())
        return "[]";

    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (;;) {
        E e = i.next();
        sb.append(e == this ? "(this Collection)" : e);
        if (! i.hasNext())
            return sb.append(']').toString();
        sb.append(", ");
    }
}

Building the string yourself will be far more efficient.


If you really want to aggregate the strings beforehand in some sort of List, you should provide your own method to efficiently join them, e.g. like this:

static String join(Collection<?> items, String sep) {
    if(items.size() == 0)
        return "";

    String[] strings = new String[items.size()];
    int length = sep.length() * (items.size() - 1);

    int idx = 0;
    for(Object item : items) {
        String str = item.toString();
        strings[idx++] = str;
        length += str.length();
    }

    char[] chars = new char[length];
    int pos = 0;

    for(String str : strings) {
        str.getChars(0, str.length(), chars, pos);
        pos += str.length();

        if(pos < length) {
            sep.getChars(0, sep.length(), chars, pos);
            pos += sep.length();
        }
    }

    return new String(chars);
}

Rather than depending on ArrayList.toString() implementation, you could write a one-liner, if you are using java 8:

String result = sList.stream()
                     .reduce("", String::concat);

If you prefer using StringBuffer instead of String since String::concat has a runtime of O(n^2), you could convert every String to StringBuffer first.

StringBuffer result = sList.stream()
                           .map(StringBuffer::new)
                           .reduce(new StringBuffer(""), StringBuffer::append);

Next variation on Peter Lawrey's answer without initialization of a new string every loop turn

String concatList(List<String> sList, String separator)
{
    Iterator<String> iter = sList.iterator();
    StringBuilder sb = new StringBuilder();

    while (iter.hasNext())
    {
        sb.append(iter.next()).append( iter.hasNext() ? separator : "");
    }
    return sb.toString();
}

Assuming it's faster to just move a pointer / set a byte to null (or however Java implements StringBuilder#setLength), rather than check a condition each time through the loop to see when to append the delimiter, you could use this method:

public static String Intersperse (Collection<?> collection, String delimiter)
{
    StringBuilder sb = new StringBuilder ();
    for (Object item : collection)
    {
        if (item == null) continue;
        sb.append (item).append (delimiter);
    }
    sb.setLength (sb.length () - delimiter.length ());
    return sb.toString ();
}

Depending on the need for performance and amount of elements to be added, this might be an ok solution. If the amount of elements are high, the Arraylists reallocation of memory might be a bit slower than StringBuilder.


Using the Functional Java library, import these:

import static fj.pre.Monoid.stringMonoid;
import static fj.data.List.list;
import fj.data.List;

... then you can do this:

List<String> ss = list("foo", "bar", "baz");
String s = stringMonoid.join(ss, ", ");

Or, the generic way, if you don't have a list of Strings:

public static <A> String showList(List<A> l, Show<A> s) {
  return stringMonoid.join(l.map(s.showS_()), ", ");
}

if you have json in your dependencies.you can use new JSONArray(list).toString()


In java 8 you can also use a reducer, something like:

public static String join(List<String> strings, String joinStr) {
    return strings.stream().reduce("", (prev, cur) -> prev += (cur + joinStr));
}

참고URL : https://stackoverflow.com/questions/523871/best-way-to-concatenate-list-of-string-objects

반응형