문자열 처리
1. 기본 문자열 함수
length
: 문자열의 길이를 반환합니다.1 2
val str = "Hello, Kotlin!" println(str.length) // 14
substring(startIndex, endIndex)
: 문자열의 일부를 잘라내어 반환합니다.1 2 3
val str = "Hello, Kotlin!" val subStr = str.substring(0, 5) println(subStr) // Hello
plus
: 문자열을 이어붙이는 함수 (연산자+
와 동일한 기능).1 2 3
val greeting = "Hello" val name = "Kotlin" println(greeting.plus(", ").plus(name)) // Hello, Kotlin
2. 문자열 비교
compareTo
: 문자열을 비교하여 결과를 반환 (0
: 동일, 음수: 작음, 양수: 큼).1 2 3
val str1 = "apple" val str2 = "banana" println(str1.compareTo(str2)) // 음수 반환 (-1)
equals
: 문자열이 같은지 비교.1 2 3
val str1 = "Kotlin" val str2 = "Kotlin" println(str1.equals(str2)) // true
==
연산자: 코틀린에서 문자열 비교는==
연산자를 사용해도 동일하게 동작합니다. 이는equals
메서드를 호출하는 것과 같습니다.1 2 3
val str1 = "Kotlin" val str2 = "Kotlin" println(str1 == str2) // true
3. 문자열 검색
contains
: 문자열에 특정 문자열이 포함되어 있는지 확인.1 2
val str = "Hello, Kotlin!" println(str.contains("Kotlin")) // true
indexOf
: 특정 문자의 첫 번째 인덱스를 반환. 찾지 못하면-1
을 반환.1 2
val str = "Hello, Kotlin!" println(str.indexOf("Kotlin")) // 7
lastIndexOf
: 문자열 내에서 특정 문자의 마지막 인덱스를 반환.1 2
val str = "Hello, Kotlin, Kotlin!" println(str.lastIndexOf("Kotlin")) // 14
startsWith
/endsWith
: 문자열이 특정 접두사 또는 접미사로 시작하거나 끝나는지 확인.1 2 3
val str = "Hello, Kotlin!" println(str.startsWith("Hello")) // true println(str.endsWith("Kotlin!")) // true
4. 문자열 변경
replace
: 특정 문자를 다른 문자로 변경.1 2
val str = "Hello, Kotlin!" println(str.replace("Kotlin", "World")) // Hello, World!
replaceFirst
: 첫 번째로 일치하는 문자열만 변경.1 2
val str = "Kotlin is Kotlin" println(str.replaceFirst("Kotlin", "Java")) // Java is Kotlin
toUpperCase
/toLowerCase
: 문자열을 대문자 또는 소문자로 변환.1 2 3
val str = "Hello, Kotlin!" println(str.toUpperCase()) // HELLO, KOTLIN! println(str.toLowerCase()) // hello, kotlin!
5. 문자열 분리 및 결합
split
: 문자열을 특정 구분자를 기준으로 분리하여 리스트로 반환.1 2 3
val str = "apple,banana,cherry" val fruits = str.split(",") println(fruits) // [apple, banana, cherry]
joinToString
: 리스트나 배열을 특정 구분자로 연결하여 하나의 문자열로 결합.1 2 3
val fruits = listOf("apple", "banana", "cherry") val result = fruits.joinToString(", ") println(result) // apple, banana, cherry
6. 문자열 반복 및 처리
repeat
: 문자열을 지정한 횟수만큼 반복.1 2
val str = "Kotlin" println(str.repeat(3)) // KotlinKotlinKotlin
forEach
: 문자열의 각 문자를 순회.1 2 3 4 5 6 7 8 9 10
val str = "Kotlin" str.forEach { char -> println(char) } // K // o // t // l // i // n
7. 문자열 트리밍
trim
: 문자열의 양 끝에 있는 공백 제거.1 2
val str = " Hello, Kotlin! " println(str.trim()) // Hello, Kotlin!
trimStart
/trimEnd
: 시작 또는 끝의 공백만 제거.1 2 3
val str = " Hello, Kotlin! " println(str.trimStart()) // "Hello, Kotlin! " println(str.trimEnd()) // " Hello, Kotlin!"
8. 문자열 템플릿 (String Templates)
코틀린에서 문자열 내에 변수를 쉽게 삽입할 수 있는 템플릿 기능을 제공합니다.
$
기호로 변수 삽입: 문자열 내에$
를 사용하여 변수를 삽입.1 2 3
val name = "Kotlin" val greeting = "Hello, $name!" println(greeting) // Hello, Kotlin!
표현식을 중괄호로 감싸서 삽입: 복잡한 표현식은
${}
로 감싸서 삽입.1 2 3
val apples = 3 val oranges = 5 println("I have ${apples + oranges} fruits") // I have 8 fruits
String 과 StringBuilder
1. String
불변성:
String
은 불변(immutable) 객체입니다. 즉, 문자열이 한번 생성되면 그 값을 변경할 수 없습니다. 문자열을 조작하는 메서드를 호출할 때마다 새로운 문자열 객체가 생성됩니다.예를 들어, 문자열에 무언가를 추가하거나 변경하는 경우, 기존 문자열을 수정하는 것이 아니라 새로운 문자열을 반환합니다.
1 2 3 4
val str = "Hello" val newStr = str + " World" println(newStr) // Hello World println(str) // Hello (기존 문자열은 그대로)
성능: 문자열을 자주 변경해야 하는 상황에서
String
을 사용하면, 매번 새로운 객체를 생성하기 때문에 메모리 및 성능에 영향을 줄 수 있습니다. 이런 경우는StringBuilder
를 사용하는 것이 더 적합합니다.사용 예시:
1 2 3
val name = "Kotlin" val greeting = "Hello, " + name println(greeting) // Hello, Kotlin
2. StringBuilder
가변성:
StringBuilder
는 가변(mutable) 객체입니다. 즉, 생성된 이후에도 문자열의 내용을 자유롭게 수정할 수 있습니다. 문자열을 추가하거나 삭제할 때마다 새로운 객체를 만들지 않고 내부의 버퍼를 수정하므로, 문자열을 자주 변경해야 할 때 성능 상 이점이 있습니다.성능: 문자열을 반복적으로 추가, 삭제, 변경하는 작업이 많을 경우
StringBuilder
는 성능 측면에서 매우 효율적입니다. 특히 반복문 안에서 문자열을 여러 번 결합할 때는String
보다StringBuilder
를 사용하는 것이 좋습니다.사용 예시:
1 2 3
val builder = StringBuilder("Hello") builder.append(" World") println(builder.toString()) // Hello World
주요 메서드:
append()
: 문자열을 이어 붙입니다.1 2 3
val builder = StringBuilder("Kotlin") builder.append(" is fun") println(builder.toString()) // Kotlin is fun
insert()
: 특정 위치에 문자열을 삽입합니다.1 2 3
val builder = StringBuilder("Kotlin") builder.insert(6, " Programming") println(builder.toString()) // Kotlin Programming
delete()
: 문자열의 일부를 삭제합니다.1 2 3
val builder = StringBuilder("Kotlin Programming") builder.delete(6, 17) println(builder.toString()) // Kotlin
reverse()
: 문자열을 뒤집습니다.1 2 3
val builder = StringBuilder("Kotlin") builder.reverse() println(builder.toString()) // niltoK
3. String과 StringBuilder의 차이점
특성 | String | StringBuilder |
---|---|---|
불변성(Immutable) | 불변 (변경 불가) | 가변 (내용 수정 가능) |
새 객체 생성 여부 | 변경 시마다 새로운 객체 생성 | 내부 버퍼에서 직접 수정 |
성능 | 문자열을 자주 수정하면 성능이 저하될 수 있음 | 문자열을 자주 수정할 때 더 빠르고 효율적임 |
사용 용도 | 불변 문자열이 필요한 경우 (일반 문자열 처리) | 자주 수정되는 문자열이 필요한 경우 (문자열 결합, 반복) |
스레드 안전성 | 불변이므로 스레드 안전 | 스레드 안전하지 않음 (StringBuffer 는 스레드 안전) |
4. 언제 사용해야 하는가?
String
사용: 문자열이 변경되지 않거나 자주 변경되지 않을 경우String
을 사용하는 것이 적합합니다. 예를 들어, 상수 문자열이나 간단한 텍스트 처리에는String
을 사용합니다.StringBuilder
사용: 문자열을 자주 변경하거나 반복적으로 추가, 삭제, 결합 등의 작업을 해야 하는 경우에는StringBuilder
를 사용하는 것이 성능 면에서 유리합니다. 특히, 반복문 내에서 문자열을 여러 번 수정할 때StringBuilder
가 더 효율적입니다.
결론
String
은 불변성이 보장되며, 문자열을 수정할 필요가 없는 경우나 간단한 문자열 처리에 적합합니다.StringBuilder
는 문자열을 빈번하게 수정하거나 결합하는 경우 성능 이점을 제공합니다.
list.sort( ) 와 sorted(list)
1. .sort()
- 리스트를 직접 변경하는 함수입니다. 즉, 원본 리스트를 제자리에서(in-place) 정렬합니다.
MutableList
에서만 사용할 수 있습니다.- 반환값이 없으며, 정렬된 상태로 리스트를 변경합니다.
|
|
2. sorted()
- 새로운 정렬된 리스트를 반환하는 함수입니다. 즉, 원본 리스트는 변경되지 않고, 정렬된 새 리스트를 반환합니다.
List
와MutableList
모두에서 사용할 수 있습니다.- 불변 리스트(immutable list) 또는 변경 불가능한 리스트를 정렬할 때 유용합니다.
|
|
차이점 요약:
특성 | .sort() | sorted() |
---|---|---|
리스트 변경 여부 | 원본 리스트를 직접 변경함 | 원본 리스트는 그대로 두고, 새로운 리스트 반환 |
사용 가능한 리스트 타입 | MutableList 에서만 사용 가능 | List 와 MutableList 모두 사용 가능 |
반환 값 | 반환 값 없음 (Unit ) | 정렬된 새로운 리스트 반환 |
언제 사용할까?
.sort()
: 이미MutableList
가 있고, 그 리스트를 바로 정렬하고자 할 때 사용합니다. 원본 리스트가 필요 없고, 즉시 정렬된 리스트로 사용하려는 경우 적합합니다.sorted()
: 원본 리스트를 유지하면서 새로운 정렬된 리스트가 필요한 경우 사용합니다. 불변 리스트(List
)를 다룰 때 적합하며,sorted()
는 원본 데이터를 변경하지 않고 안전하게 사용할 수 있습니다.
null 의 의미
개발에서 null
이라는 것은 “값이 없음” 또는 “정의되지 않은 상태” 를 의미합니다. 이는 특정 변수나 객체가 어떤 값을 가지고 있지 않음을 나타내는 값입니다. 하지만 단순히 값이 없는 상태를 의미하는 것 이상의 개념을 가지고 있으며, 개발에서 여러 가지 의미를 내포할 수 있습니다.
null
은 값이 없음, 정의되지 않음, 또는 적용 불가능한 상태를 나타내며, 다양한 맥락에서 사용됩니다.이는 프로그래밍에서 결여된 정보를 명시적으로 나타내는 방식이며, 잘못된 참조로 인해 예외를 발생시키거나 시스템 오류를 유발할 가능성이 있습니다.
1. 값이 없음 (Absence of a Value)
설명:
null
은 특정 변수나 필드가 값을 가지고 있지 않음을 명시적으로 나타냅니다.의미: 해당 변수가 초기화되지 않았거나, 그 위치에 값이 존재하지 않는 상황을 의미합니다.
예시:
1
var name: String? = null // name 변수에 값이 없음
실제 의미: 이 경우 변수
name
에 아무 값도 할당되지 않았음을 의미합니다. 즉, 메모리 공간은 할당되었지만 해당 공간에 유효한 값은 저장되지 않은 상태입니다.
2. 초기화 되지 않음 (Uninitialized or Not Applicable)
설명: 특정 변수나 객체가 아직 초기화되지 않았거나, 적용되지 않는 상태를 나타낼 때 사용됩니다.
의미: 예를 들어, 어떤 데이터베이스 조회에서 값을 찾지 못했을 때, 해당 필드에
null
이 반환될 수 있습니다.예시:
1
val result = database.findUserById(1) // 사용자가 없으면 null 반환
실제 의미:
null
이 반환되었다면, 데이터베이스에서 사용자 ID1
에 해당하는 데이터가 없거나, 해당 값이 아직 설정되지 않았음을 의미합니다.
3. 알 수 없는 상태 (Unknown State)
설명: 특정 정보가 알 수 없는 상태에 있을 때도
null
이 사용됩니다. 이 경우 해당 값이 존재하지 않는 것이 아니라, 현재 값을 알 수 없거나 결정되지 않은 상태를 나타냅니다.의미: 아직 값을 제공하지 않은 경우에 사용될 수 있으며, 그 값이 나중에 설정될 가능성이 있습니다.
예시:
1
var score: Int? = null // 아직 점수가 입력되지 않음
실제 의미:
score
는 아직 입력되지 않았지만, 나중에 점수가 입력될 수 있음을 의미합니다.
4. 오류 가능성 또는 예외 처리 필요 (Error Handling)
설명:
null
값은 오류 또는 예외 상황을 나타낼 수 있습니다. 특히, 값이 예상대로 설정되지 않았거나, 실패한 작업을 나타낼 때null
이 사용될 수 있습니다.의미: 이 경우
null
이 함수나 메서드의 실패를 의미할 수 있으며, 이를 처리해야 하는 로직이 필요합니다.예시:
1
val connection = database.getConnection() ?: throw Exception("Connection failed")
실제 의미: 데이터베이스 연결이 실패했을 때,
null
이 반환되고 예외를 발생시켜야 하는 상황을 나타냅니다.
5. 의도적 비활성화 (Intentional Absence)
설명: 개발자가 특정 값이 의도적으로 비활성화되었음을 나타내기 위해
null
을 사용하기도 합니다. 즉, 값이 없다는 것이 명시적으로 선택된 경우입니다.의미: 어떤 값이나 객체가 사용되지 않을 것임을 명시적으로 나타냅니다.
예시:
1
var logger: Logger? = null // 로깅 기능이 필요 없을 때 null
실제 의미: 이 경우
logger
객체는 의도적으로 설정되지 않았으며, 필요할 때만 설정되거나 아예 사용되지 않을 것임을 의미합니다.