CodeKata
알고리즘 풀면서 map을 많이 사용했는데 다른 사람의 풀이를 보니 hashMap을 많이 사용하여서 차이점이 궁금해서 찾아보았다.
Map
key-value를 가진 집합으로 중복을 허용하지 않는다.
한 개의 key에 한 개의 value가 매칭된다.
TreeMap, HashTable, HashMap 등이 있다.
정리하면 Key-Value로 이루어진 데이터의 집합으로 순서는 유지되지 않으며, 키는 중복을 허용하지 않는다.
HashMap
map의 특징인 key-value의 쌍으로 이루어지며, key 또는 value 값으로써 null을 허용한다.
TreeMap
HashMap과 비슷하지만 SortedMap을 상속하여 key값들이 정렬이 이루어진다.
HashTableMap
key, value 값으로써 null을 허용하지 않는다.
오늘의 Kotlin 문법
Kotlin In Action
- SAM 생성자
Single Abstract Method(단일 추상 메소드)
단 하나의 추상화 함수를 가지고 있는 함수형 인터페이스를 뜻한다.
fun interface PracSAM {
fun sam()
}
내부에 메서드 하나만 있으면 SAM 인터페이스이다.
사용 예제
예전에 Java로 OnClickListener 인터페이스 생성해서 onClick만들어서 사용해 본 기억이 있다.
코틀린에서는 setOnClickListener로 사용해서 몰랐는데 나도 모르게 SAM을 사용하고있었다.
Java의 OnClickListener
button.setOnClickListener(object: OnClickListener{
override fun onClick(p0:View?) {
...
}
})
Kotlin
button.setOnClickListener {
...
}
- with / apply / buildString
with
fun alphabet(): String {
val result = StringBuilder()
for (letter in 'A'..'Z') {
result.append(letter)
}
result.append("\n this is alphabet")
return result.toString()
}
fun alpha(): String {
val stringBuilder = StringBuilder()
return with(stringBuilder) {
for (letter in 'A'..'Z') {
this.append(letter) //1
}
append("\n this is alpha") //2
this.toString()
}
}
fun alpha1() = with(StringBuilder()){
for(letter in 'A'..'Z'){
append(letter)
}
append("\n this is alpha1")
this.toString()
}
fun main() {
println(alphabet())
println(alpha())
}
apply
- 거의 with와 같다.
- 유일한 차이는 apply는 항상 자신에게 전달된 객체를 반환한다는 점 뿐이다.
fun applyAlpha() = StringBuilder().apply {
for(letter in 'A'..'Z'){
append(letter)
}
append("\n this is apply")
}.toString()
이런 apply 함수는 객체의 인스턴스를 만들면서 즉시 프로퍼티 중 일부를 초기화해야 하는 경우 유용하다.
buildString
fun buildStringAlpha() = buildString {
for(letter in 'A'..'Z'){
append(letter)
}
append("\n this is buildString")
}
- StringBuilder 객체를 만드는 일과 toString을 호출해주는 일을 알아서 한다.
- StringBuilder를 활용해 String을 만든 경우 사용할 수 있는 해법이다.
- DSL을 만들 때 매우 유용한 도구이다.(코인액 11장-아직안배움)
- null 처리 (아직 공부중)
코틀린과 자바의 가장 중요한 차이는 코틀린 타입 시스템이 null이 될 수 있는 타입을 명시적으로 지원한다는 점이다.
fun strLen(s: String) = s.length
fun main(){
strLen(null)
}
//Null can not be a value of a non-null type String
예시 코드처럼 strLen의 s가 항상 String의 인스턴스여야 한다. 이때 컴파일러는 널이 될 수 있는 값을 strLen에게 인자로 넘기지 못하게 막는다.
fun strLenSafe(s:String?) =...
-이 함수가 널과 문자열을 인자로 받을 수 있게 하려면 타입 이름 뒤에 ?를 붙이면 된다.
+============================================
?: (엘비스 연산자)
fun foo(s: String?) {
val t: String = s ?: ""
}
null이면 좌항 null이면 우항
!!
null 아님 단언
- 어떤 값이든 null이 될 수 없는 타입으로 바꿀 수 있다.
- 실제 null에 대해 !!를 적용하면 NPE(NullPointerException)가 발생한다.
나는 null이 아님을 확신해! null일 경우 내가 감수할께! <<라는 뜻으로 쓴다.
TMI
!!기호는 마치 컴파일러에게 소리를 지르는 것 같은 느낌을 주는 무례해 보이는 기호이다. 코틀린 설계자들은 이를 의도했다. 컴파일러가 검증할 수 없는 단언을 사용하기보다는 더 나은 방법을 찾아보라는 의도를 넌지시 표현하려고 이런 기호를 택했다.
as?
- 값을 as로 지정한 타입으로 캐스트하며, 해당 타입으로 바꿀 수 없으면 ClassCastException이 발생한다.
- 이럴 경우 is 연산자를 통해 대상 값이 해당 타입으로 변환 가능한 타입인지 체크해야 하지만 코틀린에서는 as? 연산자를 제공한다.
어떤 값을 지정한 타입으로 캐스트하고, 만약 대상 타입으로 캐스트 할 수 없으면 null 반환
class PracAs(val firstName: String, val lastName: String) {
override fun equals(o: Any?): Boolean {
val otherPerson = o as? PracAs ?: return false
return otherPerson.firstName == firstName &&
otherPerson.lastName == lastName
}
override fun hashCode(): Int =
firstName.hashCode() * 37 + lastName.hashCode()
}
fun main() {
val ex1 = PracAs("so", "joo")
val ex2 = PracAs("so", "joo")
// val ex3 = PracAs("mec","joo")
println(ex1 == ex2) //true
}
Android 뿌시기
sharedPreference 복습 및 게시글 수정
bottomNavigation으로 fragment 전환 실습 복습 (내일 fragment 생명주기 이론 공부할 예정)
'Kotlin > TIL' 카테고리의 다른 글
TIL (03.27) (1) | 2024.03.27 |
---|---|
TIL (03.26) (0) | 2024.03.26 |
TIL (03.22) (1) | 2024.03.22 |
TIL (03.21) (0) | 2024.03.21 |
TIL (03.20) (0) | 2024.03.20 |