원본글: https://www.baeldung.com/java-strings-concatenation
Java에서 String객체를 잇는 방법에는 여러가지가 있는데, 그 중 몇 가지를 확인하고 나쁜(?) 코드도 확인해 보겠습니다.
1. StringBuilder
StringBuilder클래스는 String을 조작할 수 있는 여러 함수들을 제공하는데, 이를 통하여 String을 이을 수 있습니다.
@Test
void StringBuilderAppendTest() {
StringBuilder stringBuilder = new StringBuilder(100);
stringBuilder.append("hello");
stringBuilder.append(" my name is");
stringBuilder.append(" minseok");
assertEquals("hello my name is minseok", stringBuilder.toString());
}
StringBuilder를 생성할때의 크기를 100으로 지정하여 배열 확장크기 비용이 줄어듭니다.
다른 클래스로 StringBuffer라는 클래스가 있는데, 이 클래스는 StringBuilder의 동기화 버전입니다. 동기화된 버전이라 멀티쓰레드환경에서 안전할 수 있다고 생각할 수 있는데 그렇지 않습니다. 왜냐하면 StringBuffer가 가지고 있는 빌더패턴때문입니다. 따라서 멀티쓰레드 환경에서 추천하지 않습니다.
@Test
void StringBufferMultiThreadTest() {
//given
StringBuffer stringBuffer = new StringBuffer(100);
//when
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
int finalI = i;
executorService.execute(() -> {
for (int j = 0; j < 100; j++) {
stringBuffer.append(finalI);
}
});
}
executorService.shutdown();
//then
System.out.println(stringBuffer.length());
assertTrue( 10 * 100 == stringBuffer.length());
}
10개의 스레드를 생성하고 스레드 번호에 해당하는 값을 StringBuffer에 추가하는 예제입니다.
10개의 스레드에 100개의 값을 넣고 있으므로 stringBuffer의 길이는 1000이되어야합니다(10 * 100)
이 테스트는 통과할 때도 있고 통과하지 않을때도 있습니다.
이렇듯 StiringBuilder, StringBuffer는 멀티쓰레드환경에서 적합하지 않음을 확인하였습니다.
2. '+'연산자
'+'연산자를 통해서 문자열을 이을 수 있습니다.
@Test
void Operator연산자확인() {
String myString = "hello " + "my " + "name " + "is " + "minseok";
assertEquals("hello my name is minseok", myString);
}
StringBuilder와는 달리 확실히 간결하고 직관적입니다.
다만, 이 방식에는 단점이 있는데 컴파일 과정에서 결국 '+'연산자는 StringBuilder.append() 메서드를 호출하는거나 다름없어집니다. 때문에 '+' 연산자와 StringBuilder를 같이 쓰는건 굉장히 안 좋은 습관으로 통용됩니다.
또한 for문과 같은 루프 내에서 '+'연산자를 통해 문자열을 잇는다느건 그만큼 String 객체를 생성한다는것과 같기때문에 주의해야합니다. 이를 방지하기위해서는 내부 버퍼를 조작하는StringBuilder를 사용하는게 낫습니다.
3. String.concat()
@Test
void String_concat() {
String myString = "hello ".concat("my ")
.concat("name ")
.concat("is ")
.concat("minseok");
assertEquals("hello my name is minseok", myString);
}
해당 메서드는 불변성을 가진 String 객체를 반환하므로 멀티쓰레드 환경에서 안전하게 동작합니다.
4. String.fotmat()
해당 메서드는 Java의 다양한 자료형들을 해당 메서드 템플릿에 배치할 수 있습니다.
@Test
void String_format() {
String myString = String.format("%s %s %.2f %s %s, %s...", "I",
"ate",
2.5056302,
"blueberry",
"pies",
"oops");
assertEquals("I ate 2.51 blueberry pies, oops...", myString);
}
보시는것처럼 해당 메서드는 직관적인 부분도 있습니다.
5. String.join(Java8+)
해당 메서드는 코드를 보는게 더 편합니다.
@Test
void String_join_test() {
String [] strings = {"hello", "my", "name", "is", "minseok"};
String resultString = String.join(" ", strings);
assertEquals("hello my name is minseok", resultString);
}
보시면은 문자열 배열 중간중간에 특정 문자열을 넣을 수 있는 함수입니다.
이 메서드의 장점은 문자열 배열 사이에 구분기호를 어떻게 넣을지 고민을 안해도 된다는 점입니다.
6. StringJoiner(Java8+)
StringJoiner는 String.join의 기능을 사용하기 쉬운 클래스로 추상화한 것입니다.
생성자에서 구분자만 받거나 구분자, 접두사, 접미사를 받을 수 있습니다.
@Test
void StringJoiner_test() {
StringJoiner fruitJoiner = new StringJoiner(", ");
StringJoiner fruitJoiner2 = new StringJoiner(", ", "fruit: ", " end");
fruitJoiner.add("Apples");
fruitJoiner.add("Oranges");
fruitJoiner.add("Bananas");
fruitJoiner2.add("Apples");
fruitJoiner2.add("Oranges");
fruitJoiner2.add("Bananas");
assertEquals("Apples, Oranges, Bananas", fruitJoiner.toString());
assertEquals("fruit: Apples, Oranges, Bananas end", fruitJoiner2.toString());
}
String.join()과 달리 이 메서드는 배열을 먼저 생성할 필요가 없습니다.
7. Arrays.toString()
@Test
void arrayToString_test() {
String[] myFavouriteLanguages = {"Java", "JavaScript", "Python"};
String toString = Arrays.toString(myFavouriteLanguages);
assertEquals("[Java, JavaScript, Python]", toString);
}
Arrays.toString()은 String배열을 하나의 문자열로 만들어버립니다.
사용시에는 주의할 점이 2가지 있습니다.
- 첫 번째로는 배열안의 객체들이 toString()이 모두 정의되어 있어야합니다.
- 두번째로는 '[]'와 같은 대괄호가 포함된 문자열로만 리턴되어서 커스텀하기에는 불편할 수 있습니다.
8. Collectors.joining(Java 8+)
해당 메서드는 Stream의 출력을 하나의 문자열로 만들어버립니다.
@Test
void collector_join() {
List<String> awesomeAnimals = Arrays.asList("Shark", "Panda", "Armadillo");
String animalString = awesomeAnimals.stream().collect(Collectors.joining(", "));
assertEquals("Shark, Panda, Armadillo", animalString);
}
해당 메서드는 String.join()과 달리, 리스트형태의 값을 하나의 문자열로 바꿔줄 수 있습니다.
이렇듯 다양하게 문자열을 잇는 방법을 알수 있었습니다.
가변문자열인지, 고정문자열인지, 멀티쓰레드 환경에서는 안전한지, input값이 리스트형태인지 배열인지 등에 따라 다양하게 조합하여 사용할 수 있음을 알 수 있었습니다.
'Baeldung번역&공부 > Java-string' 카테고리의 다른 글
String 비교법(Comparing Strings in Java) (0) | 2025.01.28 |
---|---|
문자열 순회 방법들(How to Iterate Over the String Characters in Java) (0) | 2025.01.27 |
String Pool에 대하여(Guide to Java String Pool) (0) | 2025.01.26 |
왜 String은 불병성을 가지나(Why String Is Immutable in Java?) (0) | 2025.01.21 |
스트링 객체 초기화방법(String Initialization in Java) (0) | 2025.01.20 |