[THEC!T] 앱 스쿨2기 : Android

TECHIT 앱 스쿨 2기: Android 20일차 (23.05.23)

끝까지 처음처럼 2023. 5. 24. 00:25
728x90

자료 출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 내용

 

오늘 오전에는 어제 내주신 간단한 과제에 대하여 설명 및 중첩클래스와 데이터 클래스를 이용하여 작성하면서 개념을 설명해주셨습니다.
 
오후에는 배열과 문자열, 컬렉션에 대해서 설명해주셨습니다.
 
코틀린에서 배열은 개발자가 편한대로 작성할 수 있도록 배열관련 문법들을 지원합니다.
배운 내용과 더불어 알고 있는 내용을 조금 추가하여 작성하였으며, 이해하기 쉽도록 IntArray 을 사용하였으며 IntArray 대신 Array를 작성하여도 되며 Array로 작성할 경  코드에서는 c2에 들어가는 람다식에서 자료형을 추가하면 됩니다.
그리고 새로운 배열이 생성되는 것을 확인하기 위하여 변수를 변경하지 않고 진행하였습니다.

fun main(){
    // 기본 배열
    val a1 = arrayOf(10,20)
    val a11 = arrayOf(10,"문자",11.11)
    // a2 ~ a4 는 해당 자료형만 저장하는 배열
    // String은 일반 배열
    val a2 = intArrayOf(100,200)
    val a3 = doubleArrayOf(11.11)
    val a4 = booleanArrayOf(true, false)
    val a5 = charArrayOf('a','b','c')
    val a6 = arrayOf("문자열")
    println("배열 내용 출력 방법 .contentToString()")
    println("a1.contentToString() : ${a1.contentToString()}")

    println("---------------------------")

    // 크기가 정해져 있는 배열 생성
    // { } 안에 숫자를 적어도 되고, 규칙성 있는 배열을 만들고 싶다면
    // 람다식을 전달하여 작성할 수 있다.
    val b1 = Array(5){0}
    // it 은 인덱스 번호가 들어온다 0,1,2,3,4
    val b2 = Array(5){ (it+1)*5 }
    println("b1 : ${b1.contentToString()}")
    println("b2 : ${b2.contentToString()}")

    println("---------------------------")
    // 크기가 정해져 있는 배열에서 특정 자료형만을 저장 하는 배열
    // String 제외
    val c1 = IntArray(5){it * 5}
    println("c1 : ${c1.contentToString()}")

    // 배열의 형식이 정해져 있기 때문에 자료형을 생략한 람다식 전달 가능
    var c2 = IntArray(5){ i -> i * 10}
    println("c2 : ${c2.contentToString()}")

    println("---------------------------")

    // 자바에서는 배열에 값(객체)를 추가하는 것이 안되었지만
    // 코틀린에서는 문법 표시상으로는 추가하는 것처럼 보이게 할 수 있다.
    // 하지만 실제로는 새로운 배열을 만들어 ID를 전달한다.
    // 하기 코드는 c2에 500을 더한 배열을 생성하여 c2변수에 생성한 배열(객체)의 ID를 전달한 것이다.
    println("기존 c2 : ${c2.contentToString()}")
    println("기존 c2에 저장된 객체의 ID : $c2")
    c2 += 500
    println("c2 += 500 : ${c2.contentToString()}")
    println("c2 += 500 하고 난 후 c2에 저장된 객체의 ID: $c2")

    println("---------------------------")
    // 배열의 값(객체) 변경
    println("기존 c2 : ${c2.contentToString()}")
    c2[0] = 100
    println("c2[0] = 100 변경 : ${c2.contentToString()}")

    println("---------------------------")
    // 배열의 일부를 가져와 새로운 배열로 만들기
    println("기존 c2 : ${c2.contentToString()}")
    println("기존 c2에 저장된 객체의 ID : $c2")
    c2 = c2.sliceArray(1 .. 3)
    println("c2 : ${c2.contentToString()}")
    println("c2 = c2.sliceArray(1 .. 3) 이후 c2에 저장된 객체의 ID: $c2")

    println("---------------------------")
    // 배열이 지원하는 다양한 메서드들
    println("기존 c2 : ${c2.contentToString()}")
    println("첫 번째 값 : ${c2.first()}")
    println("마지막 값 : ${c2.last()}")
    println("30의 위치 : ${c2.indexOf(30)}")
    println("평균 : ${c2.average()}")
    println("합 : ${c2.sum()}")
    println("개수 : ${c2.count()}")
    println("개수 : ${c2.size}")
    println("30을 포함하는 가 : ${c2.contains(30)}")
    println("1000 을 포함하는 가 : ${c2.contains(1000)}")
    println("30을 포함하는 가 : ${30 in c2}")
    println("1000을 포함하는 가 : ${1000 in c2}")
    println("최대 : ${c2.max()}")
    println("최소 : ${c2.min()}")

    println("---------------------------")
    // 배열 내 저장된 값을 정렬하여 새로운 배열을 생성한다.
    var c3 = intArrayOf(100,300,200,600,500)
    println("기존 c3 : ${c3.contentToString()}")
    println("기존 c3에 저장된 객체의 ID : $c3")

    c3 = c3.sortedArray()
    println("c3.sortedArray() 결과 ${c3.contentToString()}")
    println("c3.sortedArray() 이후 객체의 ID : $c3")

    c3 = c3.sortedArrayDescending()
    println("c3.sortedArrayDescending() 결과 ${c3.contentToString()}")
    println("c3.sortedArrayDescending() 이후 객체의 ID : $c3")

    println("---------------------------")
    // 다 차원 배열 만들기
    val c4 = arrayOf(
        arrayOf(10,20,30),
        arrayOf(40,50,60),
        arrayOf(70,60,90)
    )
    println("array9 : $c4")
    println("array9 : ${c4.contentToString()}")
    println("array9 : ${c4.contentDeepToString()}")

    for(item in c4){
        for(item2 in item){
            println("item2 : $item2")
        }
    }


}

출력결과

배열 내용 출력 방법 .contentToString()
a1.contentToString() : [10, 20]
---------------------------
b1 : [0, 0, 0, 0, 0]
b2 : [5, 10, 15, 20, 25]
---------------------------
c1 : [0, 5, 10, 15, 20]
c2 : [0, 10, 20, 30, 40]
---------------------------
기존 c2 : [0, 10, 20, 30, 40]
기존 c2에 저장된 객체의 ID : [I@1d81eb93
c2 += 500 : [0, 10, 20, 30, 40, 500]
c2 += 500 하고 난 후 c2에 저장된 객체의 ID: [I@506e1b77
---------------------------
기존 c2 : [0, 10, 20, 30, 40, 500]
c2[0] = 100 변경 : [100, 10, 20, 30, 40, 500]
---------------------------
기존 c2 : [100, 10, 20, 30, 40, 500]
기존 c2에 저장된 객체의 ID : [I@506e1b77
c2 : [10, 20, 30]
c2 = c2.sliceArray(1 .. 3) 이후 c2에 저장된 객체의 ID: [I@6e2c634b
---------------------------
기존 c2 : [10, 20, 30]
첫 번째 값 : 10
마지막 값 : 30
30의 위치 : 2
평균 : 20.0
합 : 60
개수 : 3
개수 : 3
30을 포함하는 가 : true
1000 을 포함하는 가 : false
30을 포함하는 가 : true
1000을 포함하는 가 : false
최대 : 30
최소 : 10
---------------------------
기존 c3 : [100, 300, 200, 600, 500]
기존 c3에 저장된 객체의 ID : [I@31cefde0
c3.sortedArray() 결과 [100, 200, 300, 500, 600]
c3.sortedArray() 이후 객체의 ID : [I@1d56ce6a
c3.sortedArrayDescending() 결과 [600, 500, 300, 200, 100]
c3.sortedArrayDescending() 이후 객체의 ID : [I@5197848c
---------------------------
array9 : [[Ljava.lang.Integer;@2e0fa5d3
array9 : [[Ljava.lang.Integer;@5010be6, [Ljava.lang.Integer;@685f4c2e, [Ljava.lang.Integer;@7daf6ecc]
array9 : [[10, 20, 30], [40, 50, 60], [70, 60, 90]]
item2 : 10
item2 : 20
item2 : 30
item2 : 40
item2 : 50
item2 : 60
item2 : 70
item2 : 60
item2 : 90

 
배열 다음으로는 문자열에 대하여 학습하였습니다.

fun main(){
    val str = "가나다라마바사"

    // 원하는 번째에 해당하는 글자를 가져온다.
    println("str[0] : ${str[0]}")
    println("str[5] : ${str[5]}")
    // 원하는 번째에 해당하는 글자를 변경하는 것은 불가능 하다.
//    str[6] = "가"
//    str[6] = '가'
    // 하지만 특정 문구를 바꾸고 싶다면 replace() 를 사용하여
    // 새로운 문자열을 생성할 수 있다.
    val str2 = str.replace("사", "가")
    println("str.replace(\"사\", \"가\") : $str2")
    println("---------------------------------")
    // 특정 범위의 글자들을 추출하여 새로운 문자열로 받아온다.
    val str3 = str.substring(2,5)
    println("str.substring(2,5) : $str3")

    println("---------------------------------")

    // 문자열 비교
    val str4 = "Hello World"
    val str5 = "hello world"
    val str6 = "Hello World"

    // 코틀린에서 == 가지고 비교를 하면 문자열 값 자체를 비교하는 작업을 수행한다.
    if(str4 == str5){
        println("str3과 str4는 같습니다.")
    }

    if(str4 == str6){
        println("str3과 str5는 같습니다.")
    }

    // compareTo : 같으면 0. 다르면 0 이 아닌 값이 나온다.
    // compareTo 는 문자영을 구성하는 각 글자의 코드 값을 합산한 결과를 뺀 값을 전달한다.
    println(str4.compareTo(str5))
    println(str4.compareTo(str6))

    // 두 번째 매개 변수에 true를 넣어주면
    // 모두 소문자로 변환한 다음 코드값을 빼는 작업을 수행한다.
    // 대소문자를 구분하고 같은가를 확인한다.
    println(str4.compareTo(str5, true))

    // 대소문자를 무시하고 같은지를 비교한다.
    if(str4.equals(str5, true)){
        println("대소문자 무시하고 같습니다.")
    }

    println("------------------------------------")
    // 문자열 병합
    val str7 = "abc"
    // 두 문자열을 합친 새로운 문자열을 만들어 준다.
    val str8 = str7 + "def"
    // 문자열이 아닌 값을 새로운 문자열로 만든 다음
    // 두 문자열을 합친 새로운 문자열을 만들어준다.
    val str9 = str8 + 10
    println("str7 : $str7")
    println("str8 : $str8")
    println("str9 : $str9")

    // String은 문자열 합치는 작업을 수행할 때 마다 새로운 문자열 객체가
    // 계속 생성된다(String은 관리하는 문자열 수정이 불가능하기 때문에...)
    // 이럴 때는 StringBuffer를 사용한다.
    val buffer1 = StringBuffer()
    buffer1.append("abc")
    buffer1.append(100)
    buffer1.append(11.11)
    println("buffer1 : $buffer1")

    println("------------------------------------")
    // 구분자를 기준으로 문자열을 나눈다. -> 나누어 list 형태로 반환한다.
    val str10 = "가 나 다 라 마 바 사 아"
    // 공백을 기준으로 나누었다.
    val r1 = str10.split(" ")
    println("r1 : $r1")

}

출력결과

str[0] : 가
str[5] : 바
str.replace("사", "가") : 가나다라마바가
---------------------------------
str.substring(2,5) : 다라마
---------------------------------
str3과 str5는 같습니다.
-32
0
0
대소문자 무시하고 같습니다.
------------------------------------
str7 : abc
str8 : abcdef
str9 : abcdef10
buffer1 : abc10011.11
------------------------------------
r1 : [가, 나, 다, 라, 마, 바, 사, 아]

 
다음은 컬렉션 입니다.
list,map,set 등 모두 깊게 들어가면 hashMap 등등 나오지만 기본 개념 위주로 학습하였습니다.
 
List

fun main(){

    // 리스트 생성
    // 불변형 리스트
    // 리스트 생성 이후 값의 추가, 수정, 삽입, 삭제가 불가능하다.
    val list1 = listOf(10, 20 ,30, 40, 50)
    println("list1 : $list1")

    val list2 = listOf("문자열1", "문자열2", "문자열3")
    println("list2 : $list2")

    val list3 = listOf(100, 11.11, "문자열", true)
    println("list3 : $list3")

    // 수정 가능 한 리스트
    // ArrayList로 생성된다.
    val list4 = mutableListOf<Int>()
    val list5 = mutableListOf("문자열1", "문자열2", "문자열3")
    println("list4 : $list4")
    println("list5 : $list5")

    // 비어있는 수정 불가능한 리스트
    val list6 = emptyList<Int>()
    println("list6 : $list6")

    // null값을 제외하고 생성한다.
    val list7 = listOf(10, 20, null, 40, null, 60, 70)
    val list8 = listOfNotNull(10, 20, null, 40, null, 60, 70)

    println("list7 : $list7")
    println("list8 : $list8")

    println("---------------------------------------")

    // for 문 사용
    for(item in list1){
        println("item : $item")
    }

    // 개수
    println("list1.size : ${list1.size}")

    // 관리할 객체들(값들)이 있고 나중에 추가, 삭제 등을 하지 않을 경우 : arrayOf
    // 관리할 객체들(값들)이 없으며, 나중에 추가, 삭제 등을 하는 경우 : ArrayList, mutableListOf
    // 관리할 객체들(값들)이 있고 나중에 추가, 삭제 등을 하는 경우 : mutableListOf
    // 관리할 객체들(값들)이 있고 나중에 추가, 삭제 등을 하지 않고 관리하는 값을 변경하지 못하게 강제하고 할 때 : listOf

    println("---------------------------------------")
    // 관리하는 객체(값)에 접근
    // [ ] 연산자를 통해 순서값(0부터 1씩 증가)를 지정하여 접근한다.
    println("list1 0 : ${list1[0]}")
    println("list1 1 : ${list1[1]}")

    println("---------------------------------------")
    // 일부를 발췌하여 새로운 리스트로 생성한다.
    val list9 = listOf(10, 20, 30, 10, 20, 30)

    // 지정된 값이 앞에서 부터 몇 번째에 있는가
    val index1 = list9.indexOf(20)
    println("index1 : $index1")

    // 지정된 값이 뒤에서 부터 찾아서 앞에서 부터 몇 번째에 있는가
    val index2 = list9.lastIndexOf(20)
    println("index2 : $index2")

    // 일부를 발췌해 새로운 리스트로 만들어 준다.
    // 순서 값 1 ~ 3 -1 까지
    val list10 = list9.subList(1, 3)
    println("list10 : $list10")

    println("---------------------------------------")

    val list20 = listOf(10, 20, 30)
    val list21 = mutableListOf(10, 20, 30)

    // 수정 불가능한 리스트에 값 추가
    // 수정 불가능한 리스트에는 추가, 삭제, 수정, 삽입 등의 메서드가 없다.
    // list20.add(100)
    // list20[1] = 200

    // 수정이 가능한 리스트에 대한 추가, 수정, 삭제, 삽입
    // 추가
    list21.add(40)
    list21.add(50)
    list21.addAll(listOf(60, 70, 80, 90, 100))
    println("list21 : $list21")

    // 삽입
    // 순서값 1(두 번째)에 1000을 삽입하고 그 이후의 값들은 뒤로 밀린다.
    list21.add(1, 1000)
    println("list21 : $list21")

    // 순서값 3(네 번째)에 지정된 요소가 관리하는 값드을 모두 추가하고 그 이후의 값들은 뒤로 밀린다.
    list21.addAll(3, listOf(2000, 3000, 4000, 5000))
    println("list21 : $list21")

    // 제거
    // 지정된 값을 제거한다.
    list21.remove(1000)
    println("list21 : $list21")

    // 제거 하고자 하는 값이 같은 것이 여러개가 있다면 제일 앞쪽에는 값 하나만 제거한다.
    list21.add(1000)
    list21.add(1000)
    list21.add(1000)
    println("list21 : $list21")
    list21.remove(1000)
    println("list21 : $list21")

    // 없는 값을 제거
    // 아무 작업도 하지 않는다.
    list21.remove(10000)
    println("list21 : $list21")

    // 제거 하기 위해 지정한 것들을 모두 제거한다.
    list21.removeAll(listOf(2000, 3000, 4000, 5000))
    println("list21 : $list21")

    // removeAll을 통해 같은 값이 다수 저장되어 있는 것을 제거
    list21.removeAll(listOf(1000))
    println("list21 : $list21")

    // 위치를 지정하여 제거한다.
    // 두 번재 값을 제거한다.
    list21.removeAt(1)
    println("list21 : $list21")

    // 값을 수정한다.
    // 두 번재 값을 200으로 덮어 씌운다.
    list21.set(1, 200)
    println("list21 : $list21")

    list21[2] = 300
    println("list21 : $list21")

    println("---------------------------------------")
    val list100 = listOf(10, 20, 30, 40, 50)

    // list 안에 저장되어 있는 객체(값)을 추출하여 mutableList로 생성하여 반환한다.
    val list200 = list100.toMutableList()
    list200.add(60)

    println("list100 : $list100")
    println("list200 : $list200")

    // mutableList 안에 저장되어 있는 객체(값)을 추출하여 list로 생성하여 반환한다.
    val list300 = list200.toList()
    // list300.add(70)

}

출력결과

list4 : []
list5 : [문자열1, 문자열2, 문자열3]
list6 : []
list7 : [10, 20, null, 40, null, 60, 70]
list8 : [10, 20, 40, 60, 70]
---------------------------------------
item : 10
item : 20
item : 30
item : 40
item : 50
list1.size : 5
---------------------------------------
list1 0 : 10
list1 1 : 20
---------------------------------------
index1 : 1
index2 : 4
list10 : [20, 30]
---------------------------------------
list21 : [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
list21 : [10, 1000, 20, 30, 40, 50, 60, 70, 80, 90, 100]
list21 : [10, 1000, 20, 2000, 3000, 4000, 5000, 30, 40, 50, 60, 70, 80, 90, 100]
list21 : [10, 20, 2000, 3000, 4000, 5000, 30, 40, 50, 60, 70, 80, 90, 100]
list21 : [10, 20, 2000, 3000, 4000, 5000, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 1000, 1000]
list21 : [10, 20, 2000, 3000, 4000, 5000, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 1000]
list21 : [10, 20, 2000, 3000, 4000, 5000, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 1000]
list21 : [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 1000]
list21 : [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
list21 : [10, 30, 40, 50, 60, 70, 80, 90, 100]
list21 : [10, 200, 40, 50, 60, 70, 80, 90, 100]
list21 : [10, 200, 300, 50, 60, 70, 80, 90, 100]
---------------------------------------
list100 : [10, 20, 30, 40, 50]
list200 : [10, 20, 30, 40, 50, 60]

 
Map

fun main(){

    // 수정 불가능한 map
    // 이름 to 값(객체)
    // 이름은 꼭 문자열이 아니어도 된다.
    val map1 = mapOf("key1" to 10, "key2" to 20, "key3" to 30)
    println("map1 : $map1")

    val map2 = mapOf(10 to "str1", 20 to "str2", 30 to "str3")
    println("map2 : $map2")

    // 수정 가능한 map
    val map3 = mutableMapOf("key1" to 10, "key2" to 20, "key3" to 30)
    println("map3 : $map3")

    // mapOf 혹은 mutableMapOf를 사용할 때 제네릭을 설정하는 것을 권장하고 있다.
    // 이름과 값의 타입이 모두 같을 경우
    val map4 = mapOf<String, Int>("key1" to 10, "key2" to 20, "key3" to 30)
    println("map4 : $map4")

    // 만약 이름이나 값의 타입이 다양하게 저장된다면 Any로 설정해준다.
    val map5 = mapOf<String, Any>("key1" to 10, "key2" to 11.11)
    println("map5 : $map5")

    // 제네릭은 어떠한 경우라도 생략이 가능하기 때문에 그냥 생략하고 사용해도 된다.
    val map6 = mapOf("key1" to 10, "key2" to 20, "key3" to 30)
    val map7 = mapOf("key1" to 10, "key2" to 11.11)
    println("map6 : $map6")
    println("map7 : $map7")

    // 비어있는 map
    // 비어있는 map을 만들 때는 값이 없기 때문에 제네릭을 자동으로 설정할 수 없다.
    // 따라서 제네릭을 무조건 작성해 줘야 한다.
    val map8 = mapOf<String,Int>()
    val map9 = mutableMapOf<String, Int>()

    println("-------------------------------")
    // 관리하는 객체(값)을 가지고 온다.
    val map10 = mapOf("key1" to 10, "key2" to 20, "key3" to 30)
    val map11 = mutableMapOf("key1" to 10, "key2" to 20, "key3" to 30)

    println("map10 key1 : ${map10.get("key1")}")
    println("map11 key1 : ${map11.get("key1")}")

    println("map10 key1 : ${map10["key1"]}")
    println("map11 key1 : ${map11["key1"]}")

    println("-------------------------------")

    // 관리하는 값(객체)의 개수
    println("map1 size : ${map1.size}")

    // 이름들을 가져온다.
    println("map1 keys : ${map1.keys}")

    // 값들을 가져온다.
    println("map1 values : ${map1.values}")

    // 이 이름의 값이 있는지 확인하기
    println("map1 contains ket - key1 : ${map1.containsKey("Key1")}")
    println("map1 contains ket - key100 : ${map1.containsKey("Key100")}")

    // 이 값이 저장되어 있는지
    println("map1 contains value - 10 : ${map1.containsValue(10)}")
    println("map1 contains value - 100 : ${map1.containsValue(100)}")

    println("-------------------------------")


    val map12 = mutableMapOf("a1" to 10, "a2" to 20)
    println("map12 : $map12")

    // 추가
    map12.put("a3",30)
    println("map12 : $map12")

    map12["a4"] = 40
    println("map12 : $map12")

    // 수정 : 없는 이름으로 값을 넣어주면 추가가 되고 있는 이름으로 값을 넣어주면
    // 수정된다.
    map12["a1"] = 100
    println("map12 : $map12")

    // 삭제
    map12.remove("a1")
    println("map12 : $map12")


    println("-------------------------------")

    // mapOf -> mutableMapOf

    val map13 = mapOf("a1" to 10, "a2" to 20, "a3" to 30)

    val map14 = map13.toMutableMap()
    map14["a4"] = 40
    println("map14 : $map14")

    // mutableMapOf -> mapOf
    val map15 = map14.toMap()
    //map15["a5"] = 50

}

출력결과

map1 : {key1=10, key2=20, key3=30}
map2 : {10=str1, 20=str2, 30=str3}
map3 : {key1=10, key2=20, key3=30}
map4 : {key1=10, key2=20, key3=30}
map5 : {key1=10, key2=11.11}
map6 : {key1=10, key2=20, key3=30}
map7 : {key1=10, key2=11.11}
-------------------------------
map10 key1 : 10
map11 key1 : 10
map10 key1 : 10
map11 key1 : 10
-------------------------------
map1 size : 3
map1 keys : [key1, key2, key3]
map1 values : [10, 20, 30]
map1 contains ket - key1 : false
map1 contains ket - key100 : false
map1 contains value - 10 : true
map1 contains value - 100 : false
-------------------------------
map12 : {a1=10, a2=20}
map12 : {a1=10, a2=20, a3=30}
map12 : {a1=10, a2=20, a3=30, a4=40}
map12 : {a1=100, a2=20, a3=30, a4=40}
map12 : {a2=20, a3=30, a4=40}
-------------------------------
map14 : {a1=10, a2=20, a3=30, a4=40}

 
Set

fun main(){

    // 수정 불가능한 set
    val set1 = setOf(10, 20, 30, 10, 20, 30)
    // 수정 가능한 set
    val set2 = mutableSetOf(10, 20, 30, 10, 20, 30)
    println("set1 : $set1")
    println("set2 : $set2")

    // 추가
    set2.add(40)
    println("set2 : $set2")

    set2.add(10)
    println("set2 : $set2")

    // set -> list
    val list1 = set2.toList()
    val list2 = set2.toMutableList()

    println("list1 : $list1")
    println("list2 : $list2")

    // list -> set
    val list3 = listOf(10, 20, 30, 10, 20, 30)

    val set3 = list3.toSet()
    val set4 = list3.toMutableSet()
    println("set3 : $set3")
    println("set4 : $set4")

}

출력결과

set1 : [10, 20, 30]
set2 : [10, 20, 30]
set2 : [10, 20, 30, 40]
set2 : [10, 20, 30, 40]
list1 : [10, 20, 30, 40]
list2 : [10, 20, 30, 40]
set3 : [10, 20, 30]
set4 : [10, 20, 30]

 
마무리
오늘은 알고리즘을 공부하면서 혹은 독학을 하면서 자연스럽게 알게 되었던 개념등을 다시 복습하여 좋았습니다.
이제 코틀린 문법 중 남은 것은 쓰레드, 예외처리, 스트림 등이 있고 아마 그에 따른 과제를 작성하게 될텐데 지난 번 자바보다는 좀 더 어려운 문제가 나올 것으로 예상이 되어 걱정이 되지만, 복기를 하다 보면 좋은 결과가 있을 거라 생각 됩니다.
 
오늘의 마음가짐
모르면 공부하고, 질문하고, 이해하여 발전하는 개발자가 되자~!