Java에서 구분된 항목의 문자열을 작성하는 가장 좋은 방법은 무엇입니까?
자바 앱에서 작업하는 동안, 저는 최근에 컴마 구분된 값 목록을 만들어 다른 웹 서비스에 전달할 필요가 있었습니다.내가 즉석에서 생각해 낼 수 있는 최선의 방법은 다음과 같다.
public String appendWithDelimiter( String original, String addition, String delimiter ) {
if ( original.equals( "" ) ) {
return addition;
} else {
return original + delimiter + addition;
}
}
String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );
여러 가지 조건이 있기 때문에 이것이 그다지 효율적이지 않다는 것을 깨달았지만, 저는 최적화보다는 명확성을 추구했습니다.
Ruby에서는, 대신, 이것과 같은 것을 할 수 있습니다.그것은 훨씬 우아하게 느껴집니다.
parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");
그러나 Java에는 join 명령어가 없기 때문에 그에 상응하는 것을 찾을 수 없었습니다.
Java에서 이를 수행하는 가장 좋은 방법은 무엇일까요?
Java 8 이전 버전:
Apache의 Commons lang은 여기서 당신의 친구입니다.Ruby에서 참조하는 것과 매우 유사한 결합 방법을 제공합니다.
StringUtils.join(java.lang.Iterable,char)
Java 8:
8을 통해 가능StringJoiner
★★★★★★★★★★★★★★★★★」String.join()
방법을 보여 줍니다 다음 스니펫은 그 사용방법을 나타내고 있습니다.
StringJoiner joiner = new StringJoiner(",");
joiner.add("01").add("02").add("03");
String joinedString = joiner.toString(); // "01,02,03"
String.join(CharSequence delimiter, CharSequence... elements))
String joinedString = String.join(" - ", "04", "05", "06"); // "04 - 05 - 06"
String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
List<String> strings = new LinkedList<>();
strings.add("Java");strings.add("is");
strings.add("cool");
String message = String.join(" ", strings);
//message returned is: "Java is cool"
java.util에서 동작하는 join 스타일의 유틸리티 메서드를 작성할 수 있습니다.리스트
public static String join(List<String> list, String delim) {
StringBuilder sb = new StringBuilder();
String loopDelim = "";
for(String s : list) {
sb.append(loopDelim);
sb.append(s);
loopDelim = delim;
}
return sb.toString();
}
그런 다음 다음과 같이 사용합니다.
List<String> list = new ArrayList<String>();
if( condition ) list.add("elementName");
if( anotherCondition ) list.add("anotherElementName");
join(list, ",");
Android의 경우 Commons의 String Utils 클래스는 이용할 수 없기 때문에 이를 위해 사용하였습니다.
android.text.TextUtils.join(CharSequence delimiter, Iterable tokens)
http://developer.android.com/reference/android/text/TextUtils.html
Google의 Guava 라이브러리에는 com.google.common.base가 있습니다.이러한 작업을 해결하는 데 도움이 되는 joiner 클래스.
샘플:
"My pets are: " + Joiner.on(", ").join(Arrays.asList("rabbit", "parrot", "dog"));
// returns "My pets are: rabbit, parrot, dog"
Joiner.on(" AND ").join(Arrays.asList("field1=1" , "field2=2", "field3=3"));
// returns "field1=1 AND field2=2 AND field3=3"
Joiner.on(",").skipNulls().join(Arrays.asList("London", "Moscow", null, "New York", null, "Paris"));
// returns "London,Moscow,New York,Paris"
Joiner.on(", ").useForNull("Team held a draw").join(Arrays.asList("FC Barcelona", "FC Bayern", null, null, "Chelsea FC", "AC Milan"));
// returns "FC Barcelona, FC Bayern, Team held a draw, Team held a draw, Chelsea FC, AC Milan"
Guava의 String Utilities에 대한 기사입니다.
Java 8에서는 다음을 사용할 수 있습니다.
List<String> list = Arrays.asList("foo", "bar", "baz");
String joined = String.join(" and ", list); // "foo and bar and baz"
Stream API의 예에 대해서는 이 답변도 참조해 주십시오.
Java 8에서는 다음과 같이 할 수 있습니다.
list.stream().map(Object::toString)
.collect(Collectors.joining(delimiter));
목록에 null이 있는 경우 다음을 사용할 수 있습니다.
list.stream().map(String::valueOf)
.collect(Collectors.joining(delimiter))
는 프리픽스 및 서픽스도 지원합니다.
list.stream().map(String::valueOf)
.collect(Collectors.joining(delimiter, prefix, suffix));
일반화할 수 있지만, Java에는 가입이 없습니다.
이게 더 잘 될 수도 있어요.
public static String join(Iterable<? extends CharSequence> s, String delimiter) {
Iterator<? extends CharSequence> iter = s.iterator();
if (!iter.hasNext()) return "";
StringBuilder buffer = new StringBuilder(iter.next());
while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
return buffer.toString();
}
!("변환 가능한 문자 시퀀스")에 기반한 접근 방식을 사용합니다.")
말씀하신 대로 모든 문자열 연결로 인해 문자열이 생성되고 있습니다. StringBuilder
안 그럴 거야
★★★★StringBuilder
대신? 에서StringBuilder
★★★★★★★★★★★★★★★★★★:
가능한 경우 이 클래스는 대부분의 구현에서 더 빠르기 때문에 StringBuffer보다 우선적으로 사용할 것을 권장합니다.
하지만 내가 직접 쓰고 싶다면
package util;
import java.util.ArrayList;
import java.util.Iterable;
import java.util.Collections;
import java.util.Iterator;
public class Utils {
// accept a collection of objects, since all objects have toString()
public static String join(String delimiter, Iterable<? extends Object> objs) {
if (objs.isEmpty()) {
return "";
}
Iterator<? extends Object> iter = objs.iterator();
StringBuilder buffer = new StringBuilder();
buffer.append(iter.next());
while (iter.hasNext()) {
buffer.append(delimiter).append(iter.next());
}
return buffer.toString();
}
// for convenience
public static String join(String delimiter, Object... objs) {
ArrayList<Object> list = new ArrayList<Object>();
Collections.addAll(list, objs);
return join(delimiter, list);
}
}
오브젝트 컬렉션에 가입하기 전에 오브젝트를 문자열로 변환할 필요가 없기 때문에 오브젝트 컬렉션에 더 적합하다고 생각합니다.
Apache Commons StringUtils 클래스에는 Join 메서드가 있습니다.
자바 8
stringCollection.stream().collect(Collectors.joining(", "));
Java 8 네이티브타입
List<Integer> example;
example.add(1);
example.add(2);
example.add(3);
...
example.stream().collect(Collectors.joining(","));
Java 8 커스텀오브젝트:
List<Person> person;
...
person.stream().map(Person::getAge).collect(Collectors.joining(","));
와 String Builder 를 합니다.Separator
StringBuilder buf = new StringBuilder();
Separator sep = new Separator(", ");
for (String each : list) {
buf.append(sep).append(each);
}
구분 기호는 구분 기호를 감습니다. 기호는 구분됩니다.toString
메서드(가 빈 문자열을 반환하는 첫 번째 콜이 아닌 한)입니다.
" " " " "Separator
public class Separator {
private boolean skipFirst;
private final String value;
public Separator() {
this(", ");
}
public Separator(String value) {
this.value = value;
this.skipFirst = true;
}
public void reset() {
skipFirst = true;
}
public String toString() {
String sep = skipFirst ? "" : value;
skipFirst = false;
return sep;
}
}
이 경우 Java 유형을 사용할 수 있습니다.그리고 또StringBuffer
불필요한 이 포함되어 있습니다.
최소한의 것(문자열 결합을 위해 Apache Commons 또는 Gauva를 프로젝트 종속성에 포함시키고 싶지 않은 경우)
/**
*
* @param delim : String that should be kept in between the parts
* @param parts : parts that needs to be joined
* @return a String that's formed by joining the parts
*/
private static final String join(String delim, String... parts) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < parts.length - 1; i++) {
builder.append(parts[i]).append(delim);
}
if(parts.length > 0){
builder.append(parts[parts.length - 1]);
}
return builder.toString();
}
join() 메서드를 직접 써보는 것은 어떨까요?Strings와 딜리미터 String의 파라미터 집합으로 사용됩니다.메서드 내에서 수집을 반복하고 결과를 StringBuffer로 빌드합니다.
Spring MVC 를 사용하고 있는 경우는, 다음의 순서를 시험할 수 있습니다.
import org.springframework.util.StringUtils;
List<String> groupIds = new List<String>;
groupIds.add("a");
groupIds.add("b");
groupIds.add("c");
String csv = StringUtils.arrayToCommaDelimitedString(groupIds.toArray());
되면 …이 된다a,b,c
이클립스 컬렉션을 사용하는 경우makeString()
★★★★★★★★★★★★★★★★★」appendString()
.
makeString()
를 반환하다String
" "와 유사, 「」과 같은 표현.toString()
.
그것은 세 가지 형태가 있다.
makeString(start, separator, end)
makeString(separator)
strings 。makeString()
는 " " " 입니다.", "
영문)
코드 예:
MutableList<Integer> list = FastList.newListWith(1, 2, 3);
assertEquals("[1/2/3]", list.makeString("[", "/", "]"));
assertEquals("1/2/3", list.makeString("/"));
assertEquals("1, 2, 3", list.makeString());
assertEquals(list.toString(), list.makeString("[", ", ", "]"));
appendString()
와 유사하다makeString()
, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , .Appendable
것)StringBuilder
및 )입니다.void
이3가지 형식이 , 첫추가되어 있습니다. 이 명령어에는 동일한 3가지 형식이 있으며 첫 번째 인수인 부록이 추가됩니다.
MutableList<Integer> list = FastList.newListWith(1, 2, 3);
Appendable appendable = new StringBuilder();
list.appendString(appendable, "[", "/", "]");
assertEquals("[1/2/3]", appendable.toString());
컬렉션을 Eclipse Collections 유형으로 변환할 수 없는 경우 관련 어댑터로 수정하십시오.
List<Object> list = ...;
ListAdapter.adapt(list).makeString(",");
주의: 저는 이클립스 컬렉션의 커밋입니다.
도 아마 '어울릴 것 같다'를 할 것 같아요.StringBuilder
append
이 방법을 사용하면 Java가 제공하는 솔루션만큼 효과적입니다.
Java에서도 루비로 하고 있는 것과 같은 작업을 하면 어떨까요?즉, 어레이에 모든 부분을 추가한 후에만 구분 문자열이 생성됩니다.
ArrayList<String> parms = new ArrayList<String>();
if (someCondition) parms.add("someString");
if (anotherCondition) parms.add("someOtherString");
// ...
String sep = ""; StringBuffer b = new StringBuffer();
for (String p: parms) {
b.append(sep);
b.append(p);
sep = "yourDelimiter";
}
다른 도우미 방식으로 루프를 이동하거나 StringBuffer 대신 StringBuilder를 사용할 수도 있습니다.
편집: 추가 순서를 수정했습니다.
Java 5 변수 arg를 사용하면 모든 문자열을 컬렉션이나 배열에 명시적으로 넣을 필요가 없습니다.
import junit.framework.Assert;
import org.junit.Test;
public class StringUtil
{
public static String join(String delim, String... strings)
{
StringBuilder builder = new StringBuilder();
if (strings != null)
{
for (String str : strings)
{
if (builder.length() > 0)
{
builder.append(delim).append(" ");
}
builder.append(str);
}
}
return builder.toString();
}
@Test
public void joinTest()
{
Assert.assertEquals("", StringUtil.join(",", null));
Assert.assertEquals("", StringUtil.join(",", ""));
Assert.assertEquals("", StringUtil.join(",", new String[0]));
Assert.assertEquals("test", StringUtil.join(",", "test"));
Assert.assertEquals("foo, bar", StringUtil.join(",", "foo", "bar"));
Assert.assertEquals("foo, bar, x", StringUtil.join(",", "foo", "bar", "x"));
}
}
Spring 컨텍스트에 있는 사용자에게는 String Utils 클래스도 유용합니다.
다음과 같은 유용한 단축키가 많이 있습니다.
- collection To Comma Delimited String(컬렉션 콜)
- collection To Delimited String (컬렉션 coll, 문자열 구분자)
- arrayToDelimitedString(개체[]arr, 문자열 구분자)
그리고 다른 많은 것들도요.
이는 Java 8을 아직 사용하지 않고 Spring 컨텍스트에 있는 경우 유용합니다.
다음과 같이 Collection 지원이 용이하기 때문에 Apache Commons보다 선호합니다(매우 좋기는 하지만).
// Encoding Set<String> to String delimited
String asString = org.springframework.util.StringUtils.collectionToDelimitedString(codes, ";");
// Decoding String delimited to Set
Set<String> collection = org.springframework.util.StringUtils.commaDelimitedListToSet(asString);
다음과 같은 작업을 수행할 수 있습니다.
StringBuilder sb = new StringBuilder();
if (condition) { sb.append("elementName").append(","); }
if (anotherCondition) { sb.append("anotherElementName").append(","); }
String parameterString = sb.toString();
기본적으로 다음과 같습니다.
public static String appendWithDelimiter(String original, String addition, String delimiter) {
if (original.equals("")) {
return addition;
} else {
StringBuilder sb = new StringBuilder(original.length() + addition.length() + delimiter.length());
sb.append(original);
sb.append(delimiter);
sb.append(addition);
return sb.toString();
}
}
이것이 실제로 더 나은지는 모르겠지만 적어도 String Builder를 사용하고 있기 때문에 조금 더 효율적일 수 있습니다.
아래는 매개 변수 구분 작업을 수행하기 전에 매개 변수 목록을 작성할 수 있는 보다 일반적인 방법입니다.
// Answers real question
public String appendWithDelimiters(String delimiter, String original, String addition) {
StringBuilder sb = new StringBuilder(original);
if(sb.length()!=0) {
sb.append(delimiter).append(addition);
} else {
sb.append(addition);
}
return sb.toString();
}
// A more generic case.
// ... means a list of indeterminate length of Strings.
public String appendWithDelimitersGeneric(String delimiter, String... strings) {
StringBuilder sb = new StringBuilder();
for (String string : strings) {
if(sb.length()!=0) {
sb.append(delimiter).append(string);
} else {
sb.append(string);
}
}
return sb.toString();
}
public void testAppendWithDelimiters() {
String string = appendWithDelimitersGeneric(",", "string1", "string2", "string3");
}
이 방법은 나쁘지 않지만 + 기호를 사용하는 대신 StringBuffer를 사용해야 합니다.+는 각 단일 작업에 대해 새로운 String 인스턴스가 생성된다는 큰 단점이 있습니다.끈이 길어질수록 오버헤드는 커집니다.따라서 StringBuffer를 사용하는 것이 가장 빠른 방법입니다.
public StringBuffer appendWithDelimiter( StringBuffer original, String addition, String delimiter ) {
if ( original == null ) {
StringBuffer buffer = new StringBuffer();
buffer.append(addition);
return buffer;
} else {
buffer.append(delimiter);
buffer.append(addition);
return original;
}
}
스트링 작성을 완료한 후 반환된 String Buffer에서 String()을 호출하기만 하면 됩니다.
문자열 연결을 사용하는 대신 코드가 스레드화되지 않은 경우 String Builder를, 스레드화되지 않은 경우 String Buffer를 사용해야 합니다.
당신은 이 일을 필요 이상으로 복잡하게 만들고 있어요.먼저 예제의 끝부분부터 시작합시다.
String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );
String이 아닌 String Builder를 사용하는 방법이 약간 변경되면 다음과 같이 됩니다.
StringBuilder parameterString = new StringBuilder();
if (condition) parameterString.append("elementName").append(",");
if (anotherCondition) parameterString.append("anotherElementName").append(",");
...
작업이 끝나면(다른 조건도 몇 가지 확인해야 할 것 같습니다), 다음과 같은 명령어를 사용하여 후행 콤마를 삭제해 주세요.
if (parameterString.length() > 0)
parameterString.deleteCharAt(parameterString.length() - 1);
그리고 마지막으로, 원하는 스트링을 얻습니다.
parameterString.toString();
또한 두 번째 호출에서 " "를 대체하여 임의의 값으로 설정할 수 있는 일반 딜리미터 문자열로 추가할 수도 있습니다.추가할 필요가 있는 것(무조건) 목록이 있는 경우 문자열 목록을 사용하는 메서드에 이 코드를 넣을 수 있습니다.
//Note: if you have access to Java5+,
//use StringBuilder in preference to StringBuffer.
//All that has to be replaced is the class name.
//StringBuffer will work in Java 1.4, though.
appendWithDelimiter( StringBuffer buffer, String addition,
String delimiter ) {
if ( buffer.length() == 0) {
buffer.append(addition);
} else {
buffer.append(delimiter);
buffer.append(addition);
}
}
StringBuffer parameterBuffer = new StringBuffer();
if ( condition ) {
appendWithDelimiter(parameterBuffer, "elementName", "," );
}
if ( anotherCondition ) {
appendWithDelimiter(parameterBuffer, "anotherElementName", "," );
}
//Finally, to return a string representation, call toString() when returning.
return parameterBuffer.toString();
찾고 있는 것 같은 느낌을 받기 위해 다음과 같은 몇 가지 작업을 수행할 수 있습니다.
1) 목록 클래스 확장 - 여기에 결합 메서드를 추가합니다.join 메서드는 단순히 딜리미터(join 메서드의 파라미터일 수 있음)를 연결하고 추가하는 작업을 수행합니다.
2) Java 7은 java에 확장 메서드를 추가할 것 같습니다.이것에 의해, 특정의 메서드를 클래스에 부가하는 것만으로, 그 join 메서드를 작성해, List 또는 Collection에 확장 메서드로 추가할 수 있습니다.
Java 7이 아직 출시되지 않았기 때문에 솔루션 1은 아마도 현재 유일한 현실적인 솔루션일 것입니다:) 그러나 이 솔루션은 정상적으로 작동합니다.
이 두 가지를 모두 사용하려면 평소와 같이 목록 또는 컬렉션에 모든 항목을 추가한 다음 새로운 사용자 지정 메서드를 호출하여 '참가'하면 됩니다.
언급URL : https://stackoverflow.com/questions/63150/whats-the-best-way-to-build-a-string-of-delimited-items-in-java
'sourcecode' 카테고리의 다른 글
웹 확장의 공유 vuex 상태(데드 개체 문제) (0) | 2022.08.27 |
---|---|
TypeScript를 사용하여 Vue.js에서 비반응 인스턴스 속성을 지정하는 방법 (0) | 2022.08.27 |
로그인 후 NuxtJ 리다이렉트 (0) | 2022.08.27 |
Vuejs 이벤트 한정자 (0) | 2022.08.27 |
실 워크스페이스 및 lerna를 사용하여 vue 및 nuxt용 프론트 엔드 모노레포를 설정하는 데 도움이 필요합니다. (0) | 2022.08.27 |