데이터베이스 작업을하는 동안 쿼리 문자열을 작성하고이 문자열에서 목록 / 배열 / 컬렉션의 where-clause에 몇 가지 제한을 두어야합니다. 다음과 같이 표시되어야합니다.
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 쿼리처럼)이 복잡해질 때 처음 보면 어떤 일이 발생하는지 알 수 없습니다.
당신의 (더) 우아한 방법은 무엇입니까?
답변
참고 :이 답변은 11 년 전에 작성되었을 때 좋았지 만 이제는 Java 내장 클래스 만 사용하거나 유틸리티 라이브러리를 사용하여 한 줄로 더 깔끔하게 수행 할 수있는 훨씬 더 나은 옵션이 있습니다. 아래의 다른 답변을 참조하십시오.
문자열은 변경할 수 없으므로 코드에서 문자열을 변경하려는 경우 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): "";
답변
답변
오늘이 작업을 수행 한 코드를 살펴 보았습니다. 이것은 AviewAnew의 답변에 대한 변형입니다.
collectionOfStrings = /* source string collection */;
String csList = StringUtils.join(collectionOfStrings.toArray(), ",");
StringUtils에 (<- commons.lang 2.x에서, 또는 commons.lang 3.X 링크 ) 우리가 사용은에서이다 아파치 코 몬즈 .
답변
루프를 작성하는 방법은 다음과 같습니다.
StringBuilder buff = new StringBuilder();
String sep = "";
for (String str : strs) {
buff.append(sep);
buff.append(str);
sep = ",";
}
return buff.toString();
sep의 성능에 대해 걱정하지 마십시오. 과제는 매우 빠릅니다. 핫스팟은 어쨌든 루프의 첫 번째 반복을 벗겨내는 경향이 있습니다 (널 (null) 및 모노 / 바이 모픽 인라인 검사와 같은 이상한 항목을 처리해야하는 경우가 많으므로).
많이 사용하는 경우 (두 번 이상) 공유 방법에 넣으십시오.
SQL 문에 ID 목록을 삽입하는 방법을 다루는 stackoverflow에 대한 또 다른 질문이 있습니다.
답변
Java 8부터 다음을 사용할 수 있습니다.
String String.join(CharSequence delimiter, CharSequence... elements)
String String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
-
non-을 가져 와서에
String
결합String
하려면을 사용할 수 있습니다Collectors.joining(CharSequence delimiter)
. 예 :String joined = anyCollection.stream().map(Object::toString).collect(Collectors.joining(","));
답변
더 많은 요소에 대한 테스트가 있기 때문에 반복기 관용구가 우아하다는 것을 알았습니다 (간결성을 위해 null / empty 테스트 생략).
public static String convert(List<String> list) {
String res = "";
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
res += iterator.next() + (iterator.hasNext() ? "," : "");
}
return res;
}
답변
이에 대한 많은 수동 솔루션이 있지만 위의 Julie의 답변을 반복하고 업데이트하고 싶습니다. Google 컬렉션 Joiner 클래스를 사용하십시오 .
Joiner.on(", ").join(34, 26, ..., 2)
var args, iterables 및 array를 처리하고 하나 이상의 문자 구분 기호를 적절하게 처리합니다 (gimmel의 답변과 달리). 또한 필요한 경우 목록의 null 값을 처리합니다.