JiwonDev

StringBuffer์™€ StringBulider

by JiwonDev

2021.07.27 - [๊ธฐ๋ณธ ์ง€์‹/CS ๊ธฐ๋ณธ์ง€์‹] - ์ž๋ฐ”์˜ String๊ณผ Constant Pool

 

์ž๋ฐ”์˜ String๊ณผ Constant Pool

JVM์— ๊ด€ํ•˜์—ฌ #1. JVM ์šด์˜์ฒด์ œ์™€ ํ•˜๋“œ์›จ์–ด์— ๋…๋ฆฝ์ ์ธ ์–ธ์–ด, 1995๋…„ ๋‹น์‹œ ์ด ๊ฐœ๋…์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ˜์‹ ์ด์—ˆ๋‹ค. ์ฐธ๊ณ ๋กœ ์ž๋ฐ”๋Š” ์ฌ ๋งˆ์ดํฌ๋กœ์‹œ์Šคํ…œ์Šค๊ฐ€ ๊ฐœ๋ฐœํ–ˆ์ง€๋งŒ JVM ๋ช…์„ธ(Specification)๋งŒ ๋”ฐ๋ฅธ๋‹ค๋ฉด ๋ˆ„

jiwondev.tistory.com

์ž๋ฐ”์—์„œ ๋ฌธ์ž์—ด์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์€ String, StringBuffer, StringBuilder๊ฐ€ ์žˆ๋‹ค.

์‚ฌ์‹ค ์—ฐ์‚ฐ์ด ๋งŽ์ง€ ์•Š์„ ๋•Œ์—๋Š” 3๊ฐœ์ค‘ ์•„๋ฌด๊ฑฐ๋‚˜ ์‚ฌ์šฉํ•ด๋„ ํฐ ์ฐจ์ด๋Š” ์—†์ง€๋งŒ, ์—ฐ์‚ฐ ํšŸ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๊ฑฐ๋‚˜ ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ, Race Condition๋“ฑ์˜ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ๊ฐ ๋ฌธ์ž์—ด ํด๋ž˜์Šค์˜ ์šฉ๋„๋ฅผ ์ž˜ ์•Œ๊ณ  ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

# String

S๊ฐ€์žฅ ํฐ ํŠน์ง•์€ String์€ ์ƒ์ˆ˜. ์ฆ‰ ๋ถˆ๋ณ€(immutable)ํ•˜๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

String str = "hello"; // String str = new String("hello");
str = str + " world"; // [ hello world ]

์ฝ”๋“œ์ƒ์—์„œ๋Š” ๋งˆ์น˜ ๋ฌธ์ž์—ด์„ 'ํŽธ์ง‘' ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒ ์ง€๋งŒ, JVM ๋‚ด๋ถ€์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋™์ž‘์ด ์ผ์–ด๋‚œ๋‹ค. ์ฆ‰ ๋ฌธ์ž์—ด์„ ์กฐ์ž‘(์ถ”๊ฐ€, ์ˆ˜์ •, ์‚ญ์ œ)ํ•œ๋‹ค๋ฉด Heap ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‚ญ๋น„ํ•˜๊ณ  GC์˜ ์ž‘์—…์„ ์ถ”๊ฐ€์‹œ์ผœ ์•ฑ์˜ ์„ฑ๋Šฅ์„ ํ•˜๋ฝ์‹œํ‚จ๋‹ค.

* ์—ฅ? new๋กœ ์ƒ์„ฑํ•œ๊ฒŒ ์•„๋‹Œ ๋ฌธ์ž์—ด์€ Heap์ด ์•„๋‹ˆ๋ผ ์ •์  ์ƒ์ˆ˜๋กœ ๊ด€๋ฆฌ๋˜๋Š”๊ฑฐ ์•„๋‹ˆ์—์š”?

๋”๋ณด๊ธฐ

Java8๋ถ€ํ„ฐ๋Š” ์ƒ์ˆ˜ ํ’€๋„ Heap๋ฉ”๋ชจ๋ฆฌ์— ์œ„์น˜ํ•˜๊ฒŒ ๋œ๋‹ค. ์ฆ‰ GC์˜ ๋Œ€์ƒ์ด๋‹ค. ๋˜ํ•œ ๋ฉ”๋ชจ๋ฆฌ์ ์ธ ์ธก๋ฉด๋ฟ ์•„๋‹ˆ๋ผ ๋ฌธ์ž์—ด ์กฐ์ž‘ ์„ฑ๋Šฅ์ด ๊ตฌ๋ฆฌ๋‹ค๋Š” ๋‹จ์ ๋„ ์žˆ๋‹ค๋Š”๊ฑธ ์žŠ์ง€๋ง์ž.

 


# StringBuffer์™€ StringBuilder

String๊ณผ ๋‹ค๋ฅด๊ฒŒ ๊ฐ€๋ณ€์„ฑ(mutable)์„ ๊ฐ€์ ธ ๋ฌธ์ž์—ด ์กฐ์ž‘(์ถ”๊ฐ€, ์ˆ˜์ •, ์‚ญ์ œ) ์„ฑ๋Šฅ์ด ์ข‹๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๊ธฐ์กด์˜ String์„ ์ „๋ถ€ StringBuffer๋กœ ๋ฐ”๊พธ๋ฉด ๋˜๋Š”๊ฑฐ ์•„๋‹๊นŒ?

 

String์€ ๋‹จ์ˆœํžˆ ์ƒ์ˆ˜๋ฌธ์ž์—ด๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉด ๋˜์ง€๋งŒ, StringBuffer, Builder๋Š” ๋ฒ„ํผ์˜ ํฌ๊ธฐ๋ฅผ ์กฐ์ž‘ํ•˜๊ณ  ๋‹ค์–‘ํ•œ ์ถ”๊ฐ€ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋งŒํผ ๋‚ด๋ถ€ ๋™์ž‘์ด ๋” ๋ณต์žกํ•˜๋‹ค. ์ฆ‰ ์กฐ์ž‘ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๋ชจ๋“  String์„ StringBuffer์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š”๊ฑด ์„ฑ๋Šฅ์— ์ข‹์ง€์•Š์€ ๋ฐฉ๋ฒ•์ด๋‹ค.

StringBuffer sb= new StringBuffer("hello");
sb.append(" world");

 


@ String์˜ ์Šค๋ ˆ๋“œ ์•ˆ์ •์„ฑ

String์˜ ๊ฒฝ์šฐ ๊ฐ’์ด ๋ถˆ๋ณ€ํ•˜๊ธฐ์— ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผ, ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ํ•˜์ง€๋งŒ StringBuilder์˜  str.append() ์—ฐ์‚ฐ์ฒ˜๋Ÿผ ๋ฌธ์ž์—ด์ด ๋ถˆ๋ณ€ํ•˜์ง€ ์•Š๊ณ  ๊ธธ์ด๊ฐ€ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ ‘๊ทผ ํ–ˆ์„ ๋•Œ ์–ด๋–ค ๋ฌธ์ œ์ ์ด ์žˆ์„๊นŒ?

์ŠคํŠธ๋ง ๊ฐ’์„ ์‚ฌ์šฉํ•จ์— ์žˆ์–ด DB์˜ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ, ์ฆ‰ ๋™๊ธฐํ™”๋ฅผ ํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด ์ •๋ง ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด [์“ฐ๋ ˆ๋“œ1]์ด ๋ฌธ์ž์—ด์„ ํŽธ์ง‘ํ•˜๊ณ  ์žˆ๋Š” ๋„์ค‘์— [์“ฐ๋ ˆ๋“œ2]๊ฐ€ ์ ‘๊ทผํ•œ๋‹ค๋ฉด ํŽธ์ง‘๋˜๋‹ค๊ฐ€ ๋ง์€ ์ด์ƒํ•œ ๊ฐ’์„ ๊ฐ€์ ธ๊ฐ€๊ฑฐ๋‚˜, ํ˜น์€ ๋™์‹œ์— ์ ‘๊ทผํ•œ [์“ฐ๋ ˆ๋“œ2]๊ฐ€ [์“ฐ๋ ˆ๋“œ1]์˜ ์ž‘์—… ๊ฒฐ๊ณผ๋ฅผ ๋ฌด์‹œํ•˜๊ณ  ๋ฎ์–ด์”Œ์šฐ๋Š” ๋“ฑ ์ •๋ง ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

 


@ StringBuffer vs StringBuilder, ์ฐจ์ด์ 

๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์€ ๋™๊ธฐํ™”์˜ ์œ ๋ฌด์ด๋‹ค. ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด StringBuffer๋Š” ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉ์„ ์œ„ํ•ด ๋งŒ๋“ค์—ˆ๋‹ค.

  • String:  ๋ฌธ์ž์—ด ์—ฐ์‚ฐ์ด ์ ๊ณ  ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์ผ ๊ฒฝ์šฐ (๊ฐ’์ด ๋ณ€ํ•˜์ง€ ์•Š์•„ ์•ˆ์ „ํ•˜๋‹ค.)
  • StringBuffer:  ๋ฌธ์ž์—ด ์—ฐ์‚ฐ์ด ๋งŽ๊ณ  ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์ผ ๊ฒฝ์šฐ (๊ฐ’์ด ๋ณ€ํ•˜์ง€๋งŒ, thread-safe๋ฅผ ๋ณด์žฅํ•œ๋‹ค.)
  • StringBuilder:  ๋ฌธ์ž์—ด ์—ฐ์‚ฐ์ด ๋งŽ๊ณ  ๋‹จ์ผ์“ฐ๋ ˆ๋“œ์ด๊ฑฐ๋‚˜ ๋™๊ธฐํ™”๋ฅผ ๊ณ ๋ คํ•˜์ง€ ์•Š์•„๋„ ๋˜๋Š” ๊ฒฝ์šฐ

 StringBuffer์˜ ๊ฒฝ์šฐ ์ž๋ฐ”์˜ synchronized ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•ด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ์˜ ๋™๊ธฐํ™”, thread-safe๋ฅผ ๋ณด์žฅํ•œ๋‹ค.

// StringBuilder.append()
@Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
// StringBuffer.append()
  @Override
  public synchronized StringBuffer append(String str) {
      toStringCache = null;
      super.append(str);
      return this;
  }

 

๋‹ค๋งŒ ๋™๊ธฐํ™”๋ฅผ ๋ณด์žฅํ•˜๋Š” ์ž‘์—…์€ ์„ฑ๋Šฅ์„ ํฌ๊ฒŒ ํ•˜๋ฝ์‹œํ‚จ๋‹ค. ์ฆ‰ StringBuffer์˜ ์‚ฌ์šฉ์€ ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ, ๋‹จ์ผ์“ฐ๋ ˆ๋“œ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด '๋™๊ธฐํ™”' ๊ธฐ๋Šฅ์˜ ์ถ”๊ฐ€ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์ด ํ•˜๋ฝ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”์—†๋Š” ๋‹จ์ผ ์“ฐ๋ ˆ๋“œ์—์„œ ์‚ฌ์šฉํ•ด๋ผ๊ณ  ๋งŒ๋“  StringBuilder๋ฅผ ๋”ฐ๋กœ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์ฐธ๊ณ ๋กœ ๋Œ€์šฉ๋Ÿ‰ ๋ฌธ์ž์—ด ์กฐ์ž‘ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ StrinBuilder๊ฐ€ 1์ดˆ ๊ฑธ๋ ธ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด,

  • ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋™๊ธฐํ™”๋ฅผ ๋ณด์žฅํ•˜๋Š” StringBuffer๋Š” 2์ดˆ
  • ๊ทธ๋ƒฅ ์กฐ์ž‘ํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” String์€ 2400์ดˆ(40๋ถ„)์ •๋„ ๊ฑธ๋ฆฐ๋‹ค.

์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒ ์ง€๋งŒ ์‹ค์ œ ํ…Œ์ŠคํŠธ ํ•ด๋ณด๋ฉด ๋น„์Šทํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ JDK1.5๋ถ€ํ„ฐ๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์—์„œ String ๋ง์…ˆ์ด StringBuilder๋กœ ์ž๋™ ์น˜ํ™˜๋œ๋‹ค.

 


# Java ์ปดํŒŒ์ผ๋Ÿฌ์˜ String ์ตœ์ ํ™”

์‹ค์ œ๋กœ String๊ณผ StringBuffer๋Š” ์žฅ๋‹จ์ ์ด ์žˆ์—ˆ๊ธฐ์— ๊ด€๋ จ๋œ ๋…ผ์˜๊ฐ€ ๋งŽ์•˜๋‹ค. ๊ทธ๋ž˜์„œ JDK1.5 ์ดํ›„ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” String ์ฒ˜๋ฆฌ์— ์žˆ์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐ”์ดํŠธ์ฝ”๋“œ ๋ณ€ํ™˜ ์ „ ์ตœ์ ํ™”๋ฅผ ๋ณด์žฅํ•œ๋‹ค.

  • ํ•œ์ค„์—์„œ ์ƒ์ˆ˜ String์˜ ๋ง์…ˆ์€ ์•„์˜ˆ ํ•œ ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊ฟ”์„œ ์ปดํŒŒ์ผํ•œ๋‹ค.
  • Java 1.5 ์ดํ›„์˜ String ๋ง์…ˆ ์—ฐ์‚ฐ์€ ์ „๋ถ€ StringBuilder๋กœ ์น˜ํ™˜๋œ๋‹ค.
  • ์ฆ‰ ํ•œ์ค„์—์„œ ์ƒ์ˆ˜์™€ ๋‹ค๋ฅธ String ํด๋ž˜์Šค๋ฅผ ๋”ํ•˜๋Š”๊ฑด StringBuilder.append() .toString() ๋ฉ”์„œ๋“œ๋กœ ๋ฐ”๊พผ๋‹ค.

์‹ค์ œ๋กœ JDK 1.5๋ฒ„์ „ ์ดํ›„๋กœ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ String๋งŒ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ์ ์ ˆํ•˜๊ฒŒ StringBuffer๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค.

//๊ธฐ์กด ์ž๋ฐ”์ฝ”๋“œ
public static void main(String args[]) {
    String str0 = "It's a string....";
    String str1 = "It's a string....";
    String str2 = "It's a string...." + str0 + "000";
    str2 = str0 + str1 + "1111";
    str2 = str2 + "1111";
    str2 = str2 + "1111";
    for (int i = 0; i < 10; i++) {
        str2 = str2 + "1111";
        str2 = str2 + "1111";
    }

}
// jdk1.5 ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ตœ์ ํ™” ์‹œํ‚จ ์ฝ”๋“œ.
public static void main(String args[]) {
    String str0 = "It's a string....";
    String str1 = "It's a string....";
    String str2 = (new StringBuilder("It's a string....")).append(str0).append("000").toString();
    str2 = (new StringBuilder(String.valueOf(str0))).append(str1).append("1111").toString();
    str2 = (new StringBuilder(String.valueOf(str2))).append("1111").toString();
    str2 = (new StringBuilder(String.valueOf(str2))).append("1111").toString();
    for (int i = 0; i < 10; i++) {
        str2 = (new StringBuilder(String.valueOf(str2))).append("1111").toString();
        str2 = (new StringBuilder(String.valueOf(str2))).append("1111").toString();
    }
}

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ