코틀린-안드로이드

13일차)알고리즘 문제(달리기 경주), 코트카타 리뷰, 코틀린 문법 강의 4주차(접근제한자, 예외 처리, 지연초기화, 널 세이프티, 배열, 컬렉션, 싱클)

songyooho 2024. 6. 4. 21:02

>알고리즘 문제

1. 문제

 

2. 솔루션

class Solution {
    fun solution(players: Array<String>, callings: Array<String>): Array<String> {
        var answer: Array<String> = arrayOf<String>()
        var map=mutableMapOf<String,Int>()
        for(i in 0..players.size-1){
            map.put(players[i],i)
        }
        var arr=players
        for(i in 0..callings.size-1){
            var calledName=callings[i]
            var calledRank=map[calledName]
            var frontName=arr[calledRank!!-1]
            var frontRank=calledRank!!-1
            
            //map 수정
            var tmpR=calledRank
            map[calledName]=frontRank
            map[frontName]=tmpR!!
            
            //arr 수정
            var tmpN=calledName
            arr[calledRank]=frontName
            arr[frontRank]=tmpN
        }
        answer=arr
        return answer
    }
}

- callings의 길이가 백만까지도 갈 수 있기 때문에 각 원소별 접근으로 생기는 시간을 최소화하기 위해 mutableMap과 Array를 둘다 생성하였다.

-특정 인물의 등수를 알기위해서는 Map으로 접근하고 특정 등수에 있는 인물의 이름을 알기위해서는 array로 접근한다.

-각 call이 발생할 때 마다 map과 arr을 수정해준다.

 

 

>코드카타 리뷰

1)map의 value값을 사용할때 null처리를 해줘야 하는 이유: key값이 존재하지 않는 경우 value값이 null이 나올 수도 있기 때문에 null처리를  해줘야 한다.

2)solution의 parameter를 수정가능한 종류가 있는 이유: val이라도 내부 객체 직접 수정은 가능

-모든 parameter로 들어온 인자는 val처리됨

-하지만 mutable 컬렉션이나 Array의 경우 val처리해도 수정이 가능함.

=>val처리 된 것은 저장된 메모리의 주소값이기 때문에 주소가 바뀔수 없는 것이지 객체 내부값은 변경 가능하다. 

=>즉 참조 형식으로 저장된 값은 내부값 변경 가능

3)참조타입 비교(배열)

-==,!=: 참조비교가 되므로 사용하면 안 됨(문자열 제외)

-contentEquals(): 주로 사용

@문자열 비교시 equals를 사용해도 되나 contentEquals() 사용시 String,StringBuffer,StringBuilder,CharBuffer등 끼리도 비교 가능

 

 

>코틀린 문법 강의 4주차

 

1. 접근제한자

1)용어정리

-프로젝트: 최상단개념. 모듈,패키지,클래스를 포함. 

-모듈: 패키지,클래스 포함. 안드로이드 스튜디오에서 app부분에 해당

-패키지: 클래스 포함. 안드로이드 스튜디오에선 java 내의 kt파일들이 들어있는 폴더를 지칭

 

2)종류

-public: 명시안하면 기본 값. 어디서든 접근가능

-private: 클래스 내부에서만 접근 가능

-internal: 같은 모듈 내에서만 접근 가능

-protected: 기본적으로는 private지만 상속받은 클래스에서는 접근 가능

 

2.예외 처리

1)try..catch..finally

-구조

try{
	예외발생 가능능 존재 코드
}catch(예외종류){
	예외발생시 처리 코드
}finally{
	무조건 실행되는 코드
}

@예외종류에서 Exception e사용가능

@try에서 break나 return이 실행되더라도 finally는 무조건 실행됨.

 

2)throw

-예외 던지고 싶은 부분에 throw 예외종류 

 

@@@@@@

return when(){}에서 case -> result의 result부분이 while문인 경우 다시 return 사용해서 반환 및 while문 탈출용으로 사용

예시:

return when(type) {
        "name" -> {
            println("이름을 입력해주세요")
            while(true) {
                try {
                    var originName = readLine()
                    if(originName?.first() != '_' && originName?.first() != '!') {
                        return originName
                    } else {
                        println("이름을 다시 입력해주세요")
                    }
                } catch(e:Exception) {
                    println("이름을 다시 입력해주세요")
                }
            }
        }
        .
        .
        .

@@@@@@

 

3. 지연초기화

1)변수 - lateinit을 var 앞에 붙임

<1>사용: 객체생성 이후에 값을 초기화 할 수 있게 해줌
<2>더블콜론(::): 인스턴스를 생성하지 않은 상태에서 참조하게 해줌

<3>this::name.isInitialized: 초기화 여부 확인

<4>예시

fun main(){
    var s1 = Student()
    s1.displayInfo() //"name변수를 초기화해주세요."
    s1.name = "참새"
    s1.displayInfo() // 이름과 나이 출력

    s1.age = 10
    s1.displayInfo()
}

class Student {
    lateinit var name:String
    var age:Int = 0

    fun displayInfo() {
        if(this::name.isInitialized) {
	        println("이름은: ${name} 입니다.")
	        println("나이는: ${age} 입니다.")
        } else {
            println("name변수를 초기화해주세요.")
        }
    }
}

 

2)상수 - val 변수명: 자료형 by lazy{ 본문... 마지막줄에 대입값}

<1>사용: 초기화가 안 되어 있다가 처음 해당 상수 호출 lazy뒤의 본문이 실행되면서 초기화

=>주로 처음엔 초기화가 불가능 하다가 나중에 초기화가 가능할때 사용 

<2>예시

fun main() {
    lateinit var text: String
    val textLength: Int by lazy {
        text.length
    }
    .
    .
    .
    text = "aaaa"
    println(textLength)
}

 

4. 널 세이프티

1)종류: ?, !!, ?., ?:

-? :자료형 뒤에 붙여 nullable

-!! :null인 경우 throw

-?. :널일 가능성있는 객체에 접근할때 객체가 null이면 null반환

-?: 엘비스 연산자. 앞의 값이 null인경우 대체값을 넣을 수 있음

2)!!는 사용 지양

 

5. 배열

1)사용: arrayOf(값 나열)

 

6. 컬렉션

1)List

<1>listOf(값들): 그냥 리스트. 값변경 불가

<2>mutableListOf(값들): 값 변경 가능 리스트

<3>ArrayList<자료형>(값들): 많이 사용. 가변

-add():값 추가

-remove():값 삭제

-removeAt():특정 인덱스 값 삭제

 

7. Single-expression function(람다 함수): 두 종류 존재

1)

var rambda={매개변수1, 매개변수2,... -> 코드 및 마지막줄에 반환값}

2)

fun 함수명(매개변수1, ...) = 결과값

 

7. 싱클턴

1)의미: 메모리 전역에서 유일한 객체임을 보장

2)종류

<1>object: class대신 object키워드를 붙여 만들면 객체 생성없이 접근가능

-예시

fun main() {
    Bird.fly("참새")
}

object Bird {
    fun fly(name:String) {
        println("${name}가 날아요~")
    }
}

 

<2>companion: 클래스 내부에 companion object{}로 감싼 부분만 해당됨

-객체생성없이 클래스명으로 companion object{}에 해당하는 부분 접근가능. 객체 생성해서는 접근 불가

-예시

class cL{
    companion object{
        var data=20
    }
    var o=10
}

fun main() {
    val obj=cL()
    
    obj.o=10 //성공
    cL.o=10 //오류
    println(obj.data)//오류
    println(cL.data) //성공
}