컬렉션/어레이/목록에서 쉼표로 구분된 문자열을 만드는 가장 정교한 방법은 무엇입니까?
데이터베이스 작업 중 쿼리 문자열을 쓰는 것을 알게 되었습니다.이 문자열에서는 목록/어레이/컬렉션에서 where-clause에 몇 가지 제한을 두어야 합니다.다음과 같이 표시됩니다.
select * from customer
where customer.id in (34, 26, ..., 2);
이를 단순화할 수 있습니다.문자열 컬렉션을 가지고 있으며 이 문자열의 콤마 구분 목록을 1개의 문자열에만 작성해야 합니다.
지금까지의 어프로치는, 다음과 같습니다.
String result = "";
boolean first = true;
for(String string : collectionOfStrings) {
if(first) {
result+=string;
first=false;
} else {
result+=","+string;
}
}
하지만 이것은 보시다시피 매우 추악합니다.특히 생성된 문자열(모든 SQL 쿼리와 마찬가지로)이 복잡해지면 첫눈에 무슨 일이 일어나는지 알 수 없습니다.
당신의 우아한 방법은 무엇입니까?
Google Guava API의 방법을 사용합니다.
Joiner.on(",").join(collectionOfStrings);
주의: 이 답변은 11년 전에는 좋았지만, 현재는 Java의 빌트인 클래스만 사용하거나 유틸리티 라이브러리를 사용하여 한 줄에서 보다 깔끔하게 작성할 수 있는 훨씬 더 좋은 옵션이 있습니다.아래의 다른 답변을 참조하십시오.
문자열은 불변하기 때문에 코드의 문자열을 변경할 경우 String Builder 클래스를 사용할 수 있습니다.
String Builder 클래스는 내용이 변경되었을 때 메모리를 더 할당하는 가변 String 개체로 볼 수 있습니다.
질문의 원래 제안은 중복되는 후행 콤마를 처리함으로써 보다 명확하고 효율적으로 기술할 수 있습니다.
StringBuilder result = new StringBuilder();
for(String string : collectionOfStrings) {
result.append(string);
result.append(",");
}
return result.length() > 0 ? result.substring(0, result.length() - 1): "";
오늘 이렇게 된 코드를 봤어요이것은 Aview의 변형입니다.뉴의 답.
collectionOfStrings = /* source string collection */;
String csList = StringUtils.join(collectionOfStrings.toArray(), ",");
사용한 StringUtils(<-- commons.lang 2.x 또는 commons.lang 3.x 링크)는 Apache Commons에서 가져온 것입니다.
이 루프를 쓰는 방법은 다음과 같습니다.
StringBuilder buff = new StringBuilder();
String sep = "";
for (String str : strs) {
buff.append(sep);
buff.append(str);
sep = ",";
}
return buff.toString();
9월 공연은 걱정하지 마세요.과제는 매우 빠르다.핫스팟은 루프의 첫 번째 반복을 벗겨내는 경향이 있습니다(늘 및 모노/바이모픽 인라인 체크와 같은 기묘한 문제를 처리해야 하는 경우가 많기 때문입니다).
여러 번 사용할 경우 공유 방식으로 저장하십시오.
SQL 문에 ID 목록을 삽입하는 방법을 다루는 stackoverflow에 대한 다른 질문이 있습니다.
Java 8 이후 다음 기능을 사용할 수 있습니다.
String String.join(CharSequence delimiter, CharSequence... elements)
String String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
()-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-(-)-)
String
.String
, 를 사용할 수 있습니다.예: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)
다양한 Arg, 반복 가능 및 어레이를 처리하며 여러 글자의 구분자를 적절하게 처리합니다(Gimmel의 답변과는 다릅니다.또한 필요에 따라 목록의 null 값도 처리합니다.
String.join(", ", collectionOfStrings)
Java8 api에서 사용할 수 있습니다.
(Google guava 의존관계 추가 불필요):
Joiner.on(",").join(collectionOfStrings);
다음은 이전 제안들을 조합하여 구축한 매우 일반적인 버전입니다.
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);
}
시도해 보세요.
List collections = Arrays.asList(34, 26, "...", 2);
String asString = collection.toString();
// justValues = "34, 26, ..., 2"
String justValues = asString.substring(1, asString.length()-1);
이것은 Guava 또는 Apache Commons를 사용하는 것을 제외하고 지금까지 가장 짧은 솔루션이 될 것입니다.
String res = "";
for (String i : values) {
res += res.isEmpty() ? i : ","+i;
}
0, 1 및 n 요소 목록에 적합합니다.하지만 Null 목록을 확인해야 합니다.GWT에서 사용하기 때문에 String Builder가 없어도 괜찮습니다.또, 몇개의 요소만을 포함한 쇼트 리스트의 경우는, 다른 장소에서도 문제가 없습니다.
가 이 넘어졌을 를 대비해 8을 했습니다.reduce()
또한 이미 언급한 솔루션도 포함되어 있습니다.
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, ","));
}
}
Android에서는 다음을 사용해야 합니다.
TextUtils.join(",",collectionOfStrings.toArray());
sql을 구성하는 것은 좋은 생각이 아닌 것 같습니다.where 절 값은 다음과 같습니다.
SELECT.... FROM.... WHERE ID IN( value1, value2,....valueN)
서 ★★★★★valueX
현악기
첫째, 문자열을 비교할 경우 따옴표로 묶어야 합니다. Strings 안에 따옴표가 있으면 간단하지 않습니다.
둘째, 사용자 또는 다른 시스템에서 값이 전송되면 SQL 주입 공격이 발생할 수 있습니다.
보다 상세하게 설명하지만 다음과 같은 String을 작성해야 합니다.
SELECT.... FROM.... WHERE ID IN( ?, ?,....?)
다음 을 '바꿔서 하다'로 묶습니다.Statement.setString(nParameter,parameterValue)
.
이 문제를 해결하기 위한 또 다른 방법일 뿐입니다.가장 짧지는 않지만, 효율적이고 일을 완수할 수 있습니다.
/**
* 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();
}
String Join 메서드를 제공하는 일부 서드파티 Java 라이브러리가 있지만, 이와 같은 단순한 용도로 라이브러리를 사용하기 시작하지는 않을 것입니다.이러한 도우미 메서드를 작성하면 됩니다.이것은 당신의 버전보다 조금 더 좋다고 생각합니다.String Buffer를 사용하는 것으로, 많은 스트링에 가입할 필요가 있는 경우 보다 효율적이며, 어떤 타입의 컬렉션에서도 동작합니다.
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()이 매우 구체적인 포맷으로 문자열을 반환하는 것에 의존합니다.이것은 개인적으로 신뢰하고 싶지 않습니다.
스프링을 사용하면 다음을 수행할 수 있습니다.
StringUtils.arrayToCommaDelimitedString(
collectionOfStrings.toArray()
)
org.springframework.displays)
List<String> collectionOfStrings = // List of string to concat
String csvStrings = StringUtils.collectionToDelimitedString(collectionOfStrings, ",");
springframeowrk로부터의 String Utils: 스프링 코어
이게 얼마나 세련됐는지는 모르겠지만, 확실히 좀 짧아요.다양한 종류의 컬렉션을 사용할 수 있습니다.<Integer>, <String> 등을 설정합니다.
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/empty 컬렉션을 올바르게 처리하도록 이 메서드를 수정합니다. : )
코드를 추하게 만드는 것은 첫 번째 케이스에 대한 특별한 처리입니다.이 작은 조각의 대부분의 행은 코드의 일상적인 작업을 하는 것이 아니라 특별한 경우를 처리하는 데 할애되어 있습니다.그리고 그것이 기멜과 같은 다른 대안들이 해결할 수 있는 것입니다. 특별한 핸들링을 루프 밖으로 이동시키는 것입니다.특별한 케이스가 1개 있습니다(시작과 종료 모두 특별한 케이스로 볼 수 있지만, 그 중 1개만 특별히 취급하면 됩니다).따라서 루프 내에서 취급하는 것은 불필요하게 복잡합니다.
방금 내 도서관 비용 테스트를 체크인했습니다.
@Test
public void join() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
String string = $(list).join(",");
}
리스트/스태틱 Import를 1개만 사용하여 리스트/스태틱/스태틱 등에 대해 유연한 래퍼를 만듭니다.$
.
주의:
하면 이전 을 다시 할 수 .$(1, 5).join(",")
IN 식의 장점은 반복된 값이 있는 경우 결과가 변경되지 않는다는 것입니다.첫 번째 항목을 복제하여 전체 목록을 처리하십시오.이것은 목록에 적어도1개의 항목이 있는 것을 전제로 합니다.만약 아이템이 없다면 먼저 확인하고 SQL을 전혀 실행하지 않는 것이 좋습니다.
이렇게 하면 효과가 있고, 동작도 명확하며, 외부 라이브러리에도 의존하지 않습니다.
StringBuffer inString = new StringBuffer(listOfIDs.get(0).toString());
for (Long currentID : listOfIDs) {
inString.append(",").append(currentID);
}
Guava의 Joiner를 사용하는 것이 가장 좋은 방법이라고 생각합니다만, 손으로 코드화하면, 이 어프로치가 「첫 번째」플래그나 마지막 쉼표를 잘라내는 것보다 우아하다고 생각합니다.
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();
}
어레이가 있는 경우 다음 작업을 수행할 수 있습니다.
Arrays.asList(parameters).toString()
여기에 표시되는 내용을 기반으로 한 다른 옵션입니다(약간 수정).
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();
}
및 할 수 있습니다.AbstractCollections
덮어쓰지는 않습니다.toString()
방법(거의 모든 컬렉션과 마찬가지로)java.util
).
예:
String s= java.util.Arrays.toString(collectionOfStrings.toArray());
s = s.substing(1, s.length()-1);// [] are guaranteed to be there
이는 SQL와 동일한 숫자에 대해서만 작동하기 때문에 매우 이상한 방법입니다.
(SQL에 대한) LINQ를 사용할 수 있으며 MS의 Dynamic Query LINQ 샘플을 사용할 수 있습니다.http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
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)
String commaSeparatedNames = namesList.toString().replaceAll( "[\\[|\\]| ]", "" ); // replace [ or ] or blank
문자열 표현은 반복자가 반환하는 순서대로 대괄호("[]")로 둘러싸인 컬렉션 요소 목록으로 구성됩니다.인접 요소는 문자 ", " (콤마와 공백)로 구분됩니다.
Abstract Collection javadoc
token=new ArrayList(결과), 최종 StringBuilder Builder = new 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();
언급URL : https://stackoverflow.com/questions/205555/the-most-sophisticated-way-for-creating-comma-separated-strings-from-a-collectio
'source' 카테고리의 다른 글
웹 페이지를 통해 파라미터를 PHP 스크립트로 전달하려면 어떻게 해야 합니까? (0) | 2022.11.26 |
---|---|
시제품의 목적은 무엇입니까? (0) | 2022.11.26 |
A1과 같은 테이블을 A2로 작성 (0) | 2022.11.26 |
Vue.js 또는 React 컴포넌트를 사용하는 이유 (0) | 2022.11.26 |
PHP Associative Arrays가 주문되었습니까? (0) | 2022.11.26 |