코틀린에서 CharSequenceString, StringBuilder 등 문자열과 관련된 클래스들이 구현하는 뼈대 인터페이스

val seq: CharSequence = "Hello"
println(seq.length) // 5
println(seq[2]) // l
println(seq.subSequence(1, 4)) // ell

// 접두사, 접미사 관련
val str1: CharSequence = "https://www.naver.com"
println(str1.startsWith("https://")) // true
println(str1.endsWith(".com")) // true
println(str1.removePrefix("https://")) // www.naver.com
println(str1.removeSuffix(".com")) // https://www.naver
println(str1.removeSurrounding("https://", ".com")) // www.naver

// 비어 있는지 검사하기
val emptyStr = ""
val whiteSpaces = " "
val nullStr: String? = null
println(emptyStr.isEmpty()) // true
println(whiteSpaces.isEmpty()) // false
println(emptyStr.isBlank()) // true
println(whiteSpaces.isBlank()) // true
println(nullStr.isNullOrEmpty()) // true
println(nullStr.isNullOrBlank()) // true

// 가공하기
// removeRange, padStart, padEnd, trimStart, trimEnd, trim, slice, subSequence, substring, reversed 등 제공

// 쪼개기
val hello: CharSequence = "안녕하세요.\n고맙습니다.\n반갑습니다."
val time: CharSequence = "2018-01-22"
println(hello.lines())
for (line in hello.lineSequence())
  println(line)
println(time.split('-'))
// [안녕하세요.,고맙습니다.,반갑습니다.]
// 안녕하세요.
// 고맙습니다.
// 반갑습니다.
// [2018, 01, 22]

// 문자열 찾아 바꾸기
val adage = "Love begets love."
println(adage.replace("love", "hate", ignoreCase = true))
println(adage.replaceFirst("love", "compliment", ignoreCase = true))
println(adage.replaceRange(5..10, "hello"))
// hate begets love.
// compliment begets love.
// Love hello love.

// 문자열 덧붙이기
val builder = StringBuilder().append("2018").append(" Pyeongchang")
var result = builder.toString()
println(result) // 2018 Pyeongchang

// 정규식 다루기
val regex = Regex("[0-9]+")
val str = "4324235"
val str2 = "324 6546 5432"
println(regex matches str) // true
println(regex matches str2) // false
println(regex.replace(str2, "숫자")) // 숫자 숫자 숫자

문자열 추가하고 병합하기 (substring)

s = "abcdef"
println(s.substring(0..2)) // abc
s = s.substring(0..1) + "x" + s.substring(2..s.length-1) // abxcdef

문자열 비교하기 (compare)

var s1 = "Hello Kotlin"
var s2 = "Hello KOTLIN"
// 같으면 0, s1<s2 이면 양수, 반대면 음수를 반환
println(s1.compareTo(s2))
println(s1.compareTo(s2, true)) // 대소문자 무시

StringBuilder 사용하기

: StringBuilder를 사용하면 문자열이 사용할 공간을 좀 더 크게 잡을 수 있기 때문에 문자열이 자주 변경되는 경우에 사용하면 좋습니다.

var s = StringBuilder("Hello")
s.append("World")
s.insert(10, "Added") // 인덱스 10번부터 추가
s.delete(5, 10) // 인덱스 5번부터 10번 전까지 삭제

기타 문자열 처리

: 소문자/대문자 변경(toLowerCase, toUpperCase), 특정 문자 단위로 잘라내기(split), 앞뒤 공백 제거(trim)

var deli = "Welcome to Kotlin"
val sp = deli.split(" ")
println(sp) // [Welcome, to, Kotlin]

// 하나 이상의 분리 문자를 지정
...
str.split("=", "-")

문자열을 정수로 반환하기 (toInt)

val number: Int = "123".toInt()

...
try {
  "12w".toInt()
} catch(e: NumberFormatException) {
  println(e.printStackTrace())
}

만일 숫자가 아닌 문자가 포함되었을 때 null을 반환받고자 한다면 toIntOrNull()을 사용할 수 있습니다.

형식 문자 사용하기 (format)

val pi = 3.1415926
val dec = 10
val s = "hello"
println("pi = %.2f, %3d, %s".format(pi, dec, s))

'Kotlin > String' 카테고리의 다른 글

문자열 클래스 String, StringBuffer, StringBuilder  (1) 2022.09.13
StringBuilder  (0) 2022.09.13
String  (0) 2022.09.12

String, StringBuffer, StringBuilder

자바(Java)에서 문자열을 다루는 대표적인 클래스(Class)로 String, StringBuffer, StringBuilder가 있습니다. 이 클래스들은 모두 CharSequence 인터페이스의 구현체 클래스입니다. CharSequence 인터페이스를 상속 받았다는 것은 이 클래스들 모두 내부적으로 문자열을 char[]로 다루고 있다고 보면 됩니다.

연산이 많지 않을때는 위에 나열된 어떤 클래스를 사용하더라도 문제가 발생할 가능성은 거의 없습니다. 그러나 연산횟수가 많아지거나 멀티쓰레드, Race Condition 등의 상황이 자주 발생 한다면, 각 클래스의 특징을 이해하고 상황에 맞는 적절한 클래스를 사용해야 합니다.

String

String은 불변(Immutable)의 속성을 지니고있습니다. 즉, String 타입으로 인스턴스가 한번 생성되면 변경이 안된다는 의미입니다.

String str = "피카츄"; str = str + " 라이츄"; System.out.println(str);

위 코드의 실행 결과는 아래와 같을 것입니다.

피카츄 라이츄

위의 예제를 분석할 때 "피카츄"라는 값을 가지고 있는 String 타입 참조변수 str이 가리키는 곳에 저장된 "피카츄"에 "라이츄" 문자열을 더해 "피카츄 라이츄"로 변경한 것으로 우리는 오해할 수 있습니다. 하지만, 기존에 "피카츄" 값이 들어가있던 참조변수 str이 "피카츄 라이츄"라는 값을 가지고 있는 새로운 메모리 영역을 가리키도록 변경되고 처음 선언했던 "피카츄"로 값이 할당되어 있던 메모리 영역은 가비지(Garbage)로 남았다가 GC(Garbage Collector)에 의해 소멸되는 것 입니다. String 클래스는 불변하기 때문에 문자열을 수정하는 시점에 새로운 String 인스턴스가 생성된 것입니다.

String 인스턴스

위와 같이 String은 불변성을 지니고있기 때문에 변하지 않는 문자열을 자주 읽어들이는 경우 String을 사용하면, 좋은 성능을 기대할 수 있습니다. 그러나 문자열 추가, 수정, 삭제 등의 연산이 자주 발생되는 로직에 String 클래스를 사용하면 힙 메모리(Heap Memory)에 많은 가비지(Garbage)가 생성되어 어플리케이션 성능에 악영향을 줍니다.

StringBuffer, StringBuilder

위의 String 클래스의 문제점을 해결하기 위해 Java는 가변적(Mutable)인 속성을 지닌 StringBuffer, StringBuilder 클래스를 제공하고 있습니다. String과 달리 StringBuffer와 StringBuilder는 가변적인 속성을 가지고 있기 때문에 .append() .delete() 등의 API를 이용하여 동일 객체내에서 문자열을 변경하는 것이 가능합니다. 따라서 문자열의 추가, 수정, 삭제가 자주 발생하는 경우라면 String 클래스가 아닌 StringBuffer와 StringBuilder 클래스를 사용하면 됩니다.

// StringBuffer 클래스
StringBuffer strBf = new StringBuffer("피카츄");
strBf.append(" 라이츄");
System.out.println(strBf);

// StringBuilder 클래스
StringBuilder strBd = new StringBuilder("피카츄");
strBd.append(" 라이츄");
System.out.println(strBd);
 

위의 코드를 실행하면 다음과 같은 결과가 출력됩니다.

피카츄 라이츄
피카츄 라이츄
 
 

StringBuffer, StringBuilder

StringBuffer와 StringBuilder의 차이점

동일한 API를 가지고 있는 StringBuffer와 StringBuilder의 차이점은 동기화 유무입니다. StringBuffer는 동기화 키워들를 지원하여 멀티쓰레드 환경에서 안전합니다(thread-safe). 참고로 String도 불변성을 가지기 때문에 마찬가지로 멀티쓰레드 환경에서 안전합니다.

반대로 StringBuilder는 동기화를 지원하지 않기때문에 멀티쓰레드 환경에서 사용하는 것은 적합하지 않지만 동기화를 고려하지 않는 만큼 단일 쓰레드에서의 성능은 StringBuffer 보다 뛰어납니다.

 

정리

String
StringBuffer
StringBuilder
저장소
String pool
Heap
Heap
변경
NO
YES
YES
멀티쓰레드
안전
안전
불안전
동기화
YES
YES
NO
성능
빠름
느림
빠름

 

'Kotlin > String' 카테고리의 다른 글

CharSequence  (0) 2022.09.13
StringBuilder  (0) 2022.09.13
String  (0) 2022.09.12

Kotlin string은 참조만 되지 변경하기가 어렵다. Python도 그랬던것 같다. 아마 가볍게 만들려고 그런것 같다.

공부하던중  Kotlin에도 자료구조에 사용하기 좋은 stringBuilder라는 구조를 찾았다.

StringBuilder 클래스는 String처럼 문자열을 다루는 클래스로, String에 문자열을 넣고 인스턴스 생성 후에 값을 변경하지 못했던 점을 개선한 클래스라 할 수 있다. 추가적으로 내부적으로 문자열을 저장하기 위한 메모리 공간을 지닌다. 

이놈은 append도 되고 insert, delete도 된다.  처리후 toString으로 형변환을 시켜주면 된다.

 

StringBuilder stb = new StringBuilder(32);  
이때   예시처럼 작성을 하면 생성자의 인자로 전달되는 숫자인 32 크기만큼 문자를 저장할 수 있는 공간을 마련한다. length를 찍어보면 아직까지는 0이다 메모리공간만 마련하는듯

-append(값) : 문자열 추가한다. 재미있는건 어떤 타입도 다 문자열로 바꾼다.
-delete(시작, 끝) : 시작 인덱스부터 끝 인덱스까지의 내용을 삭제한다.
-insert(위치, 값) : 특정 원하는 위치에 문자열을 추가한다.
-replace(시작, 끝, 값) : 시작 인덱스부터 끝 인덱스 이전까지의 내용을 추가하고자 하는 '값'으로 문자열을 대체한다.
-reverse() : 저장해놨던 문자열의 내용을 뒤집는다.
-substring(시작, 끝) : 저장된 문자열 중에서 시작부터 끝 이전까지의 내용만 담은 String 인스턴스의 값을 반환한다.
-deleteCharAt(위치) :  특정 위치의 값만 삭제한다.

fun main(args : Array<String>) {
    /*
    기존 참조하던 "abc" 뒤에 "def"를 추가하는 것이 아니라
    추가된 문자열 "abcdef"를 새로 생성하고 참조하는 것이다.
    그러면 쓰레기 "abc"가 남게되며 이러한 과정이 많아지면 비효율적
    var s1 = "ab"
    s1 += "cd"
    */

    val str = StringBuilder()   // 빈 생성자
    println("1. 문자열 : $str")
    /* 추가 */
    str.append(5)               // Int 타입
    str.append("man")          // String 타입
    str.append(' ')             // Char 타입
    str.append(true)            // Boolean 타입
    str.append(5431)
    str.append(" is ")
    str.append("women")

    println("2. 문자열 : $str")
    println("index=0 : ${str[0]}, index=5 : ${str[5]}")

    /* 삭제 */
    str.deleteCharAt(0) // index
    str.delete(8, 12)    // [start, end)
    println("after delete 0, 8..12 : $str")

    println("=========================================")
    val temp: String = "ABCD"
    val str2 = StringBuilder(temp)  // String을 받는 생성자
    println("1. 문자열 : $str2")
    println("길이 = ${str2.length}")
    println("뒤집기 = ${str2.reverse()}")

    str2.insert(0, "front+")   // index=0 위치에 추가
    println("2. insert front : $str2")

    val li = listOf("abc", "def", "ghi")
    str2.append(li.joinToString(""))
    println("3. append abcdefghi : $str2")

    println("4-1. 부분 문자열 : ${str2.substring(6)}")       // [6, length)
    println("4-2. 부분 문자열 : ${str2.substring(6, 9)}")        // [6, 8)
    println("4-3. 부분 문자열 : ${str2.substring(6..9)}")    // [6, 9]

    println("=========================================")
    val str3 = str.toString()   // String Type으로 저장
    if(str3 is String) println("String Type")
}

 

'Kotlin > String' 카테고리의 다른 글

CharSequence  (0) 2022.09.13
문자열 클래스 String, StringBuffer, StringBuilder  (1) 2022.09.13
String  (0) 2022.09.12

알고리즘 풀때 스트링을 자주쓰는 편인데 코틀린 String에 대해 잘 안나와 있어 코틀린 사이트에서 추려서 정리해봤다

앞 뒤문자를 짜르는 명령어가 필요했는데 결국 substring을 이용해서 만들었다고 한다.

drop 은 문자열의 앞이나 뒷부분을 자를 때 사용된다.

내부적으로는 substring 으로 구현되어 있다.

  • drop : 앞에서부터 n 개의 문자를 제거한 String 을 반환
  • dropLast: 뒤에서부터 n 개의 문자를 제거
  • dropWhile, dropLastWhile: 조건을 만족하지 않는 문자가 나올때까지 제거
  • 파이썬같이 insert나 append를 찾고 싶었어나 배열은 자료구조상 안된 arrayList에서는 가능한것 같음.
val length: Int, length : Returns the length of this character sequence.
fun compareTo(other: String): Int compare() : 스트링을 비교해서 같으면 0 다르면 차이를 int로 리턴
fun equals(other: Any?): Boolean equals(): 스트링을 비교해서 같으면 true 리턴
fun get(index: Int): Char get(idx): 지정된 index의 문자를 리턴
fun hashCode(): Int hashCode() 문자열의 해시코드를 생성
operator fun plus(other: Any?): String 2개의 스트링을 합쳐주는 연산자
fun subSequence(start: Int, end: Int): CharSequence 지정된 범위의 Char Sequence를 리턴
fun toString(): String 스트링을 리턴 ?
val String.cstr: CValues<ByteVar>  
val CharSequence.indices: IntRange Returns the range of valid character indices for this char sequence.
val CharSequence.lastIndex: Int 스트링의 마지막 문자의 인덱스를 리턴 비었으면 -1 리턴
val String.utf16: CValues<UShortVar> utf8 utf16 utf32등도 있다.
val String.wcstr: CValues<UShortVar>  
fun CharSequence.all(predicate: (Char) -> Boolean): Boolean Returns true if all characters match the given predicate.
fun CharSequence.any(): Boolean Returns true if char sequence has at least one character.
fun CharSequence.asIterable(): Iterable<Char> Creates an Iterable instance that wraps the original char sequence returning its characters when being iterated.
fun CharSequence.asSequence(): Sequence<Char> Creates a Sequence instance that wraps the original char sequence returning its characters when being iterated.
fun <K, V> CharSequence.associate(
    transform: (Char) -> Pair<K, V>
): Map<K, V>
associate
Returns a Map containing key-value pairs provided by transform function applied to characters of the given char sequence.
fun String.capitalize(locale: Locale): String  
fun String.decapitalize(locale: Locale): String  
fun CharSequence.chunked(size: Int): List<String> 지정된 사이즈로 문자시퀀스를 짤라 리스트를 만든다.
operator fun CharSequence.contains(
    other: CharSequence,
    ignoreCase: Boolean = false
): Boolean
문자열이 자신에게 포함되어 있는지
fun CharSequence.count(): Int 스트링길이
fun String.drop(n: Int): String 앞 문자를 n개 지운 스트링을 리턴한다
fun String.dropLast(n: Int): String 마지막 문자부터 n개 지운 스트링을 리턴한다.
fun String.dropWhile(predicate: (Char) -> Boolean): String 앞에서 부터 조건대로 문자를 제거
fun String.dropLastWhile(
    predicate: (Char) -> Boolean
): String
뒤에서 부터 조건대로 문자를 제거
val string = "<<<First Grade>>>"
println(string.drop(6)) // st Grade>>>
println(string.dropLast(6)) // <<<First Gr
println(string.dropWhile { !it.isLetter() }) // First Grade>>>, 앞쪽 문자가 아닌걸 제거
println(string.dropLastWhile { !it.isLetter() }) // <<<First Grade, 뒤쪽 문자가 아닌걸 제거
fun String.filter(predicate: (Char) -> Boolean): String Returns a string containing only those characters from the original string that match the given predicate.
fun String.filterIndexed(
    predicate: (index: Int, Char) -> Boolean
): String
Returns a string containing only those characters from the original string that match the given predicate.
fun String.filterNot(predicate: (Char) -> Boolean): String Returns a string containing only those characters from the original string that do not match the given predicate.
fun CharSequence.find(predicate: (Char) -> Boolean): Char? find: Returns the first character matching the given predicate, or null if no such character was found.
fun CharSequence.first(): Char Returns the first character.
fun CharSequence.firstOrNull(): Char? Returns the first character, or null if the char sequence is empty.
fun CharSequence.isEmpty(): Boolean Returns true if this char sequence is empty (contains no characters).
operator fun CharSequence.iterator(): CharIterator Iterator for characters of the given char sequence.
fun CharSequence.lines(): List<String> Splits this char sequence to a list of lines delimited by any of the following character sequences: CRLF, LF or CR.
fun <R> CharSequence.map(transform: (Char) -> R): List<R> map: Returns a list containing the results of applying the given transform function to each character in the original char sequence.
fun <R : Comparable<R>> any_iterable<R>.maxOf(selector: (Char) -> R maxOf: Returns the largest value among all values produced by selector function applied to each character in the char sequence.
fun <R : Comparable<R>> any_iterable<R>.minOf(selector: (Char) -> R minOf: Returns the smallest value among all values produced by selector function applied to each character in the char sequence.

끝이 없다. 더 보고 싶은 분은 아래 코틀린 사이트에서 공부하시길

 

 

 

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/

 

String - Kotlin Programming Language

 

kotlinlang.org

 

'Kotlin > String' 카테고리의 다른 글

CharSequence  (0) 2022.09.13
문자열 클래스 String, StringBuffer, StringBuilder  (1) 2022.09.13
StringBuilder  (0) 2022.09.13

+ Recent posts