[Kotlin] Kotlin Study #2

이제일·2023년 7월 29일
0

Kotlin

목록 보기
2/10

조건 표현식

로직 처리를 위해 Boolean을 반환하는 표현식

비교 연산자

  • 동등성 비교 ==는 내부적으로 equlas 메서드 호출
  • 이외 비교 < > 는 내부적으로 compareTo 메서드 호출
val big = 100
val small = 1

println(big > small) // big.compareTo(small) > 0 -> true
println(big < small) // big.compareTo(small) < 0 -> false
println(big >= small) // big.compareTo(small) >= 0 -> false
println(big <= small) // big.compareTo(small) <= 0 -> true
println(big == small) // big?.eqauls(small) ?: (small === null) -> false
println(big != small) // !(big?.eqauls(b)) ?: (small === null) -> true

위 변환 메서드에 따라서
동등성 비교 ==의 경우 null을 허용하지만,
이외 비교 연산은 nullable을 허용하지 않는다
참조

포함 연산자

  • 특정 범위에 속한 값의 포함 여부를 확인할 때 사용
  • 내부적으로 contains 메서드 호출
val a = 10
val b = 0..100

println(a in b) // b.contains(a) -> true
println(a !in b) // !b.contains(a) -> false

any, all, none

람다 형식으로 컬렉션의 각 값을 접근해 비교할 수 있는 메서드

  • all : 조건이 모두 참인 경우
  • none : 조건이 모두 거짓인 경우
  • any : 조건이 하나라도 참인 경우
val list = listOf<Int?>(1, 2, null)

println(list.any{ it == null }) // true
println(list.all{ it == null }) // false
println(list.none{ it == null }) // false

논리연산자

Boolean 자료형 끼리의 비교 처리
python과 같이 and or xor을 지원한다.

val t = true
val f = false

println(t && f) // false
println(t and f) // false

println(t || f) // true
println(t or f) // true

println(t xor f) // true
println(!t) // false

수식이 진행되는 와중에 값이 특정되면 연산을 멈추고 반환한다.

println(1==0 && 1/0 == 0)
// 1==0(false)에서 and 연산으로인해 값이 특정되어
// "division by zero" 에러가 나오지 않음

조건식

조건식의 결과를 판단해 처리하는 표현식으로 반환 값을 가진다

if

  • 조건식 결과를 판단한다.
  • 일반적인 if else-if else 구문이 적용된다
val number = 10

if (number < 0) {
	println("음수")
}
else if ( number > 0) {
	println("양수")
}
else{
	println("0")
}

kotlin에는 삼항연산자가 없는 대신 if block이 반환 하는 값을 이용해 비슷하게 만들 수 있다.

val result: Int = if ( 1 > 0 ) 1 else 0

when 조건

  • 분기가 여러개인 조건식이 있을 경우 사용
  • 명령문(statement), 표현식(expression)으로 사용 가능
when(x) {
    0 -> println("x == 0") // 기본적으로 == 연산 적용
    1,2 -> println("x = 1 or 2") // 콤마를 이용해 두 개 이상의 값을 하나로 처리
    in 3..5 -> println("x in 3~5") // 범위 연산
    is Int -> print("x is Int class") // 해당 Class로 안전하게 캐스팅 할 수 있어서 safe call(?.)을 사용하지 않아도 됨
}

when을 표현식으로 사용 할 때는 else구문이 필수지만,
반환 값을 특정할 수 있는Booleanselead class의 경우 나올 수 있는 분기를 모두 처리하여 else를 사용하지 않을 수 있다.

sealed class ResultOf<out T> {
	data class Success<out R>(val value: R): ResultOf<R>()
    data class Failure(
    	val message: String?, 
        val throwable: Throwable?
    ): ResultOf<Nothing>()
}
...
val result = when(response) {
	is ResultOf.Success -> ...
    is ResultOf.Failure -> ...
}
val result2 = when(1==1) {
	true -> 1
	false -> 2
}

순환 표현

범위, 진행 연산자와 메서드

  • .. :범위연산자로 정수, 문자, 문자열 사이에 지정하여 두 항목을 포함한 범위 객체를 생성
  • rangeTo : 범위 연산자와 동일함
  • until : 범위 연산자와 동일하지만, 마지막 항목이 포함되지 않음
  • downTo : 역순의 범위를 만듬
  • step : 범위의 간격을 처리함.
  • first , last , step : 범위의 첫 번째, 마지막, 간격 정보를 관리하는 속성
val range1 = 1..10 // 1, 2, ... 9, 10
val range2 = 1.ranageTo(10) // 1, 2, ... 9, 10
print(range1.first()) // 1
print(range2.last()) // 10

val rangeUntil = 1.until(10) // 1, 2, ... 8, 9
print(rangeUntil.first()) // 1
print(rangeUntil.last()) // 9

val rangeDownTo = 10.downTo(1).step(2) // 10, 8, 6, 4, 2
print(rangeDownTo.first()) // 10
print(rangeDownTo.last()) // 2
print(rangeDownTo.step()) // 2

함수 대신 연산자로 사용할 수 있다.

val rangeUntil = 1 until 10
val rangeDownTo = 10 downTo 1 step 2

반복자 - Iterator

  • 배열의 iterator() 메서드로 변환이 가능함
  • hasNextnext 메서드로 반복처리
    • hasNext : 다음 반복 요소가 있다면 true, 없다면 false 반환
    • next : 현재 Position이 가리키는 요소를 리턴하고 Position 값을 한칸 이동한다.
val iterator = listOf(1,2,3).iterator()
println(iterator.next()) // 1
println(iterator.next()) // 2
println(iterator.next()) // 3
println(iterator.next()) // Exception

반복자 - Sequence

  • 배열의 asSequence() 메서드로 변환이 가능함
  • Iterator와 다르게 position을 저장하지 않고, index에 바로 접근이 가능하다.
  • 지연계산(Lazy Evaluation)으로 수행한다.
val sequence = sequenceOf(1,2,3)
println(sequence.elementAt(0))  // 1
println(sequence.elementAt(1))  // 2
println(sequence.elementAt(2))  // 3
println(sequence.elementAt(0))  // 1

iterator vs Sequence


시퀀스의 경우 중간 처리 연산이 수행될 때마다 값을 생성해서 지연 계산을 처리하기에 성능적으로 이점을 볼 수 있지만
단순한 연산에서는 불필요한 오버헤드 때문에 Sequence가 더 느리게 동작하는 경우도 있다.

val list = 1..6
list.filter {
        println("iterator filter: $it")
    	it%2 == 0
	}.also {
    	println("iterator filter done : $it")
	}.map {
        println("iterator map: $it")
    	it * it
	}.also {
    	println("iterator map done : $it")
	}.take(2)
	.also {
        println("iterator done : $it")
    }

println()
println()
list.asSequence().filter {
        println("sequence filter: $it")
    	it%2 == 0
	}.map {
        println("sequence map: $it")
    	it * it
	}.take(2)
	.toList()
    .also {
        println("sequence done : $it")
    }
print:

iterator filter: 1
iterator filter: 2
iterator filter: 3
iterator filter: 4
iterator filter: 5
iterator filter: 6
iterator filter done : [2, 4, 6]
iterator map: 2
iterator map: 4
iterator map: 6
iterator map done : [4, 16, 36]
iterator done : [4, 16]


sequence filter: 1
sequence filter: 2
sequence map: 2
sequence filter: 3
sequence filter: 4
sequence map: 4
sequence done : [4, 16]
profile
세상 제일 이제일

0개의 댓글