복붙노트

[SQL] 컬렉션 / 배열 / 목록에서 쉼표로 구분 된 문자열을 만들기위한 가장 정교한 방법은?

SQL

컬렉션 / 배열 / 목록에서 쉼표로 구분 된 문자열을 만들기위한 가장 정교한 방법은?

데이터베이스 내 작업을하는 동안 내가 쿼리 문자열을 작성하고이 문자열에 내가 목록 / 배열 / 컬렉션에서 어디 절에 여러 가지 제한을 넣어야 할 것으로 나타났습니다. 다음과 같아야합니다 :

select * from customer 
where customer.id in (34, 26, ..., 2);

당신은 당신이 문자열의 컬렉션이 단 하나 개의 문자열이 문자열의 쉼표로 구분 된 목록을 생성 할 것인지 질문에이 감소하여이 작업을 단순화 할 수 있습니다.

내가 지금까지 사용했던 나의 접근 방식은 같은 것입니다 :

String result = "";
boolean first = true;
for(String string : collectionOfStrings) {
    if(first) {
        result+=string;
        first=false;
    } else {
        result+=","+string;
    }
}

당신은 매우 추악한 볼 수 그러나 이것은이다. 당신은 (모든 SQL 쿼리 등) 구축 된 문자열이 복잡해지고, 특히 첫 모습 거기에 무슨 볼 수 없습니다.

당신 (더) 우아한 방법은 무엇입니까?

해결법

  1. ==============================

    1.참고 :이 모두 사용하여 11 년 전에 쓴,하지만 지금은 한 줄에 더 명확하게이 작업을 수행하는 훨씬 더 나은 옵션이 때이 답변이 좋았다에만 자바 내장 클래스 또는 유틸리티 라이브러리를 사용하여. 아래의 다른 답변을 참조하십시오.

    참고 :이 모두 사용하여 11 년 전에 쓴,하지만 지금은 한 줄에 더 명확하게이 작업을 수행하는 훨씬 더 나은 옵션이 때이 답변이 좋았다에만 자바 내장 클래스 또는 유틸리티 라이브러리를 사용하여. 아래의 다른 답변을 참조하십시오.

    문자열은 불변이기 때문에, 당신은 당신이 코드에서 문자열을 변경하려고하는 경우 StringBuilder 클래스를 사용할 수 있습니다.

    StringBuilder 클래스는 그 내용이 변경되어 더 많은 메모리를 할당 변경 가능한 String 객체로 볼 수있다.

    질문의 원래 제안은 중복 콤마를 돌봐에 의해 더욱 명확하고 효율적으로 작성할 수 있습니다 :

        StringBuilder result = new StringBuilder();
        for(String string : collectionOfStrings) {
            result.append(string);
            result.append(",");
        }
        return result.length() > 0 ? result.substring(0, result.length() - 1): "";
    
  2. ==============================

    2.의 메소드 조인 구글 구아바 API를 사용합니다 :

    의 메소드 조인 구글 구아바 API를 사용합니다 :

    Joiner.on(",").join(collectionOfStrings);
    
  3. ==============================

    3.난 그냥이 오늘 한 코드를 보았다. 이 AviewAnew의 대답에 변형입니다.

    난 그냥이 오늘 한 코드를 보았다. 이 AviewAnew의 대답에 변형입니다.

    collectionOfStrings = /* source string collection */;
    String csList = StringUtils.join(collectionOfStrings.toArray(), ",");
    

    StringUtils에 (<- commons.lang 2.x에서, 또는 commons.lang 3.X 링크) 우리가 사용하는 아파치 공용에 있습니다.

  4. ==============================

    4.난 그 루프를 작성하는 방법은 다음과 같습니다

    난 그 루프를 작성하는 방법은 다음과 같습니다

    StringBuilder buff = new StringBuilder();
    String sep = "";
    for (String str : strs) {
        buff.append(sep);
        buff.append(str);
        sep = ",";
    }
    return buff.toString();
    

    9월의 성능에 대해 걱정하지 마십시오. 대입은 매우 빠릅니다. (가 종종 널 (null) 등의 기이 모노 / bimorphic 인라인 검사를 처리하는 것처럼) 핫스팟 어쨌든 루프의 첫 번째 반복을 벗겨 경향이있다.

    당신이 그것을 (한 번 이상)를 많이 사용하는 경우, 공유 방법에 넣어.

    SQL 문에 ID의 목록을 삽입하는 방법을 다루는 유래에 대한 또 다른 질문이 있습니다.

  5. ==============================

    5.자바 팔 때문에, 당신은 사용할 수 있습니다 :

    자바 팔 때문에, 당신은 사용할 수 있습니다 :

  6. ==============================

    6.나는 더 많은 요소에 대한 테스트 (간결함을 위해 생략 널 (null) / 빈 테스트)를 가지고 있기 때문에 반복자는, 우아한 관용구 발견

    나는 더 많은 요소에 대한 테스트 (간결함을 위해 생략 널 (null) / 빈 테스트)를 가지고 있기 때문에 반복자는, 우아한 관용구 발견

    public static String convert(List<String> list) {
        String res = "";
        for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
            res += iterator.next() + (iterator.hasNext() ? "," : "");
        }
        return res;
    }
    
  7. ==============================

    7.이이을 수동으로 솔루션의 많은,하지만 나는 반복 위 줄리의 답변을 업데이트하고 싶었다. 사용 구글 컬렉션 소목 클래스입니다.

    이이을 수동으로 솔루션의 많은,하지만 나는 반복 위 줄리의 답변을 업데이트하고 싶었다. 사용 구글 컬렉션 소목 클래스입니다.

    Joiner.on(", ").join(34, 26, ..., 2)
    

    그것은 (gimmel의 대답과는 달리) var에 인수, 반복 가능 객체와 배열 하나 개 이상의 문자의 적절하게 핸들 구분을 처리합니다. 당신이 그것을 필요로하는 경우에도 목록에 널 값을 처리합니다.

  8. ==============================

    8.여기에 내가 이전 제안의 조합에서 구축 한 것을 믿을 수 없을만큼 일반 버전입니다 :

    여기에 내가 이전 제안의 조합에서 구축 한 것을 믿을 수 없을만큼 일반 버전입니다 :

    public static <T> String buildCommaSeparatedString(Collection<T> values) {
        if (values==null || values.isEmpty()) return "";
        StringBuilder result = new StringBuilder();
        for (T val : values) {
            result.append(val);
            result.append(",");
        }
        return result.substring(0, result.length() - 1);
    }
    
  9. ==============================

    9.

    String.join(", ", collectionOfStrings)
    

    자바 (8) API를 제공.

    대안 (구글 구아바 종속성을 추가 할 필요없이) :

    Joiner.on(",").join(collectionOfStrings);
    
  10. ==============================

    10.당신은 시도 할 수

    당신은 시도 할 수

    List collections = Arrays.asList(34, 26, "...", 2);
    String asString = collection.toString();
    // justValues = "34, 26, ..., 2"
    String justValues = asString.substring(1, asString.length()-1);
    
  11. ==============================

    11.이 구아바 또는 아파치 코 몬즈를 사용하는 것을 제외하고, 지금까지 가장 짧은 솔루션이 될 것입니다

    이 구아바 또는 아파치 코 몬즈를 사용하는 것을 제외하고, 지금까지 가장 짧은 솔루션이 될 것입니다

    String res = "";
    for (String i : values) {
        res += res.isEmpty() ? i : ","+i;
    }
    

    0.1 및 n 개의 요소 목록에 좋은. 그러나 당신은 널리스트를 확인해야합니다. 내가 거기에 모두 StringBuilder없이 좋은거야, 그래서 나는, GWT에서 이것을 사용합니다. 그리고 너무 다른 요소의 확인을 불과 몇 짧은 목록에 대한)

  12. ==============================

    12.경우에는 사람이 더 최근에이 비틀 거렸다, 나는 () 자바 8 줄이기 사용하여 간단한 변화를 추가했습니다. 또한 다른 사람이 이미 언급 한 솔루션의 일부를 포함 :

    경우에는 사람이 더 최근에이 비틀 거렸다, 나는 () 자바 8 줄이기 사용하여 간단한 변화를 추가했습니다. 또한 다른 사람이 이미 언급 한 솔루션의 일부를 포함 :

    import java.util.Arrays;
    import java.util.List;
    
    import org.apache.commons.lang.StringUtils;    
    
    import com.google.common.base.Joiner;
    
    public class Dummy {
      public static void main(String[] args) {
    
        List<String> strings = Arrays.asList("abc", "de", "fg");
        String commaSeparated = strings
            .stream()
            .reduce((s1, s2) -> {return s1 + "," + s2; })
            .get();
    
        System.out.println(commaSeparated);
    
        System.out.println(Joiner.on(',').join(strings));
    
        System.out.println(StringUtils.join(strings, ","));
    
      }
    }
    
  13. ==============================

    13.안드로이드에서는 이것을 사용한다 :

    안드로이드에서는 이것을 사용한다 :

    TextUtils.join(",",collectionOfStrings.toArray());
    
  14. ==============================

    14.나는 당신이하고있는 것처럼 where 절 값을 연결는 SQL 좋은 아이디어 구조하지 생각 :

    나는 당신이하고있는 것처럼 where 절 값을 연결는 SQL 좋은 아이디어 구조하지 생각 :

    SELECT.... FROM.... WHERE ID IN( value1, value2,....valueN)
    

    어디 valueX는 문자열 목록에서 온다.

    당신이 문자열을 비교하는 경우 첫째,이 문자열은 따옴표 안에있을 수있는 경우이 그것은 사소한되지 않습니다, 인용해야합니다.

    값이 사용자 또는 다른 시스템에서 오는 경우 둘째, 다음, SQL 인젝션 공격이 가능합니다.

    그것은 훨씬 더 자세한 있어요하지만 당신이해야하는 것은이 같은 문자열을 만들 수 있습니다 :

    SELECT.... FROM.... WHERE ID IN( ?, ?,....?)
    

    다음 Statement.setString (nParameter,가 parameterValue)와 변수를 결합한다.

  15. ==============================

    15.그냥 다른 방법은이 문제를 해결합니다. 아니 가장 짧은, 그것은 효율적이고 일을 얻을 수 있지만.

    그냥 다른 방법은이 문제를 해결합니다. 아니 가장 짧은, 그것은 효율적이고 일을 얻을 수 있지만.

    /**
     * Creates a comma-separated list of values from given collection.
     * 
     * @param <T> Value type.
     * @param values Value collection.
     * @return Comma-separated String of values.
     */
    public <T> String toParameterList(Collection<T> values) {
       if (values == null || values.isEmpty()) {
          return ""; // Depending on how you want to deal with this case...
       }
       StringBuilder result = new StringBuilder();
       Iterator<T> i = values.iterator();
       result.append(i.next().toString());
       while (i.hasNext()) {
          result.append(",").append(i.next().toString());
       }
       return result.toString();
    }
    
  16. ==============================

    16.이 문자열을 제공하는 방법을 결합 일부 타사 자바 라이브러리가있다, 그러나 당신은 아마 그런 일을 단순에 대한 라이브러리를 사용하기 시작하고 싶지 않아요. 난 그냥 당신이 많은 문자열을 가입해야하는 경우 더 효율적입니다 StringBuffer를를 사용, 당신의 버전보다 조금 더 좋은 생각이 같은 도우미 메서드를 만들 것이고, 그것은 모든 유형의 집합에서 작동합니다.

    이 문자열을 제공하는 방법을 결합 일부 타사 자바 라이브러리가있다, 그러나 당신은 아마 그런 일을 단순에 대한 라이브러리를 사용하기 시작하고 싶지 않아요. 난 그냥 당신이 많은 문자열을 가입해야하는 경우 더 효율적입니다 StringBuffer를를 사용, 당신의 버전보다 조금 더 좋은 생각이 같은 도우미 메서드를 만들 것이고, 그것은 모든 유형의 집합에서 작동합니다.

    public static <T> String join(Collection<T> values)
    {
        StringBuffer ret = new StringBuffer();
        for (T value : values)
        {
            if (ret.length() > 0) ret.append(",");
            ret.append(value);
        }
        return ret.toString();
    }
    

    Collection.toString ()를 사용하여 또 다른 제안은 짧은,하지만 개인적으로에 의존하고 싶지 않을 것이다 매우 구체적인 형식으로 문자열을 반환 () Collection.toString에 의존한다.

  17. ==============================

    17.당신이 봄을 사용하는 경우, 당신은 할 수 있습니다 :

    당신이 봄을 사용하는 경우, 당신은 할 수 있습니다 :

    StringUtils.arrayToCommaDelimitedString(
        collectionOfStrings.toArray()
    )
    

    (패키지 org.springframework.util)

  18. ==============================

    18.나는이 얼마나 "정교한"잘 모르겠지만, 확실히 조금 짧은입니다. 그것은 여러 가지 다른 유형의 수집 예를 들어,의와 함께 작동합니다 설정 <정수>, 목록 <문자열> 등

    나는이 얼마나 "정교한"잘 모르겠지만, 확실히 조금 짧은입니다. 그것은 여러 가지 다른 유형의 수집 예를 들어,의와 함께 작동합니다 설정 <정수>, 목록 <문자열> 등

    public static final String toSqlList(Collection<?> values) {
    
        String collectionString = values.toString();
    
        // Convert the square brackets produced by Collection.toString() to round brackets used by SQL
        return "(" + collectionString.substring(1, collectionString.length() - 1) + ")";
    }
    

    독자를위한 운동 : 그래서 제대로 널 (null) / 빈 집합을 처리하는이 방법을 수정 :)

  19. ==============================

    19.어떤 코드가 추한 만드는 것은 첫 번째 경우에 대한 특수 처리이다. 이 작은 조각에서 라인의 대부분은하지 코드의 일상적인 일을하는,하지만 특별한 경우 처리에 헌신하고 있습니다. 그리고의 어떤 기멜의 같은 대안, 루프 외부에 특수 처리를 이동하여 해결할 수있다. 루프가 불필요하게 복잡 내부에서 그렇게 처리, - 하나 특별한 경우가 있습니다 (하지만 그들 중 하나는 특별하게 취급 될 필요가 아니라, 당신은 특별한 경우로 시작과 끝을 모두 볼 수 있습니다).

    어떤 코드가 추한 만드는 것은 첫 번째 경우에 대한 특수 처리이다. 이 작은 조각에서 라인의 대부분은하지 코드의 일상적인 일을하는,하지만 특별한 경우 처리에 헌신하고 있습니다. 그리고의 어떤 기멜의 같은 대안, 루프 외부에 특수 처리를 이동하여 해결할 수있다. 루프가 불필요하게 복잡 내부에서 그렇게 처리, - 하나 특별한 경우가 있습니다 (하지만 그들 중 하나는 특별하게 취급 될 필요가 아니라, 당신은 특별한 경우로 시작과 끝을 모두 볼 수 있습니다).

  20. ==============================

    20.나는 체크 단지 한 내 라이브러리 달러에 대한 테스트 :

    나는 체크 단지 한 내 라이브러리 달러에 대한 테스트 :

    @Test
    public void join() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        String string = $(list).join(",");
    }
    

    $ : 그것은 단지 하나의 정적 가져 오기를 사용하여 목록 / 배열 / 문자열 / 등 주위에 유창 래퍼를 만들 수 있습니다.

    NB :

    범위를 이전 목록을 사용하는 것은 $로 재기록 될 수있다 (1, 5) .join ( ",")

  21. ==============================

    21.은 IN 표현의 좋은 점은 값을 반복 한 경우, 그 결과를 변경하지 않습니다. 그래서, 단지 첫 번째 항목을 복제하고 전체 목록을 처리합니다. 이 목록에서 하나 개 이상의 항목이 있다고 가정합니다. 항목이 없으면, 그 제 모든에서 SQL을 실행하지를 확인하는 게 좋을 것.

    은 IN 표현의 좋은 점은 값을 반복 한 경우, 그 결과를 변경하지 않습니다. 그래서, 단지 첫 번째 항목을 복제하고 전체 목록을 처리합니다. 이 목록에서 하나 개 이상의 항목이 있다고 가정합니다. 항목이 없으면, 그 제 모든에서 SQL을 실행하지를 확인하는 게 좋을 것.

    이 트릭을 할 것, 그것이 무엇을하고 있는지에 분명하고 있으며, 외부의 라이브러리에 의존하지 않습니다

    StringBuffer inString = new StringBuffer(listOfIDs.get(0).toString());
    for (Long currentID : listOfIDs) {
      inString.append(",").append(currentID);
    }
    
  22. ==============================

    22.내가 생각하는 동안 나는 그것을 손으로 나는 '처음'플래그가 오프 마지막 쉼표를 자르고이 방법이 더 우아 찾을 코드 인 경우에 가장 좋은 건, 구아바에서 소목을 사용하는 것입니다.

    내가 생각하는 동안 나는 그것을 손으로 나는 '처음'플래그가 오프 마지막 쉼표를 자르고이 방법이 더 우아 찾을 코드 인 경우에 가장 좋은 건, 구아바에서 소목을 사용하는 것입니다.

    private String commas(Iterable<String> strings) {
        StringBuilder buffer = new StringBuilder();
        Iterator<String> it = strings.iterator();
        if (it.hasNext()) {
            buffer.append(it.next());
            while (it.hasNext()) {
                buffer.append(',');
                buffer.append(it.next());
            }
        }
    
        return buffer.toString();
    }
    
  23. ==============================

    23.당신이 배열이있는 경우 당신은 할 수 있습니다 :

    당신이 배열이있는 경우 당신은 할 수 있습니다 :

    Arrays.asList(parameters).toString()
    
  24. ==============================

    24.또 다른 옵션은, 내가 (약간의 수정을) 여기에 표시되는 내용을 기반으로.

    또 다른 옵션은, 내가 (약간의 수정을) 여기에 표시되는 내용을 기반으로.

    public static String toString(int[] numbers) {
        StringBuilder res = new StringBuilder();
        for (int number : numbers) {
            if (res.length() != 0) {
                res.append(',');
            }
            res.append(number);
        }
        return res.toString();
    }
    
  25. ==============================

    25.가입 '방법'배열과 AbstractCollections을 연장하지만 (java.util의 거의 모든 컬렉션처럼) toString () 메소드를 오버라이드 (override)하지 않는 클래스에서 사용할 수 있습니다.

    가입 '방법'배열과 AbstractCollections을 연장하지만 (java.util의 거의 모든 컬렉션처럼) toString () 메소드를 오버라이드 (override)하지 않는 클래스에서 사용할 수 있습니다.

    예를 들어 :

    String s= java.util.Arrays.toString(collectionOfStrings.toArray());
    s = s.substing(1, s.length()-1);// [] are guaranteed to be there
    

    그것은 단지 모두 데이터가 현명한 SQL 번호를 작동하기 때문에 그것은 아주 이상한 방법입니다.

  26. ==============================

    26.

    List<String> collectionOfStrings = // List of string to concat
    String csvStrings = StringUtils.collectionToDelimitedString(collectionOfStrings, ",");
    

    스프링 코어 : springframeowrk에서 StringUtils에

  27. ==============================

    27.당신은 (SQL에) LINQ를 사용할 수 있습니다, 당신은 MS에서 동적 쿼리 LINQ 샘플을 활용할 수 있습니다. http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

    당신은 (SQL에) LINQ를 사용할 수 있습니다, 당신은 MS에서 동적 쿼리 LINQ 샘플을 활용할 수 있습니다. http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

  28. ==============================

    28.

    java.util.List<String> lista = new java.util.ArrayList<String>();
    lista.add("Hola");
    lista.add("Julio");
    System.out.println(lista.toString().replace('[','(').replace(']',')'));
    
    $~(Hola, Julio)
    
  29. ==============================

    29.

    String commaSeparatedNames = namesList.toString().replaceAll( "[\\[|\\]| ]", "" );  // replace [ or ] or blank
    
  30. ==============================

    30.토큰 = 새로운 ArrayList를 (결과) 목록; 최종의 StringBuilder 빌더 = 새의 StringBuilder ();

    토큰 = 새로운 ArrayList를 (결과) 목록; 최종의 StringBuilder 빌더 = 새의 StringBuilder ();

        for (int i =0; i < tokens.size(); i++){
            builder.append(tokens.get(i));
            if(i != tokens.size()-1){
                builder.append(TOKEN_DELIMITER);
            }
        }
    

    () builder.toString;

  31. from https://stackoverflow.com/questions/205555/the-most-sophisticated-way-for-creating-comma-separated-strings-from-a-collectio by cc-by-sa and MIT license