[TIL] 2023. 12. 10

Gahyeon Lee·2023년 12월 10일
0

TIL

목록 보기
22/47
post-thumbnail

🥜 배열

1. 배열이란?

  • 일반적으로 변수를 선언하면 코틀린은 메모리에 띄엄띄엄 랜덤으로 생성해서 변수의 위치정보가 연속적이지 않기 때문에 순서가 없다.
  • 배열을 이용하면 변수에 순서를 매겨 연속적으로 활용할 수 있다.
  • 코틀린은 배열을 사용하기 위해 arrayOf 메소드(키워드)를 제공한다.(내장 메소드)
  • 크기가 정해져 있어서 처음에 5개짜리를 만들었다면 5개까지만 넣을 수 있다.
import java.util.Arrays   // Arrays에 error가 떠서 import해 줌(외부패키지에 있는 클래스를 import한 것)

fun main() {
// arrayOf메소드를 호출하면 배열을 리턴해준다.
// 1,2,3,4,5 각각을 저장한 변수 5개를 배열형태로 arr에 저장
    var arr = arrayOf(1, 2, 3, 4, 5)    // 이 arrayOf는 내가 만든 메소드, 클래스가 아니라 java.util.Arrays라는 클래스 안에 있는 메소드여서 다른 패키지에 있는 것을 불러와야 한다.
                                        // arrayOf에 파라미터 5개를 넣어줬다. 하나하나가 다 변수라고 생각하면 된다.
// 배열요소를 모두 출력
    println(Arrays.toString(arr))       // Arrays에 error가 뜨면 import를 해주자.
                                        // Arrays 안에는 toString이라는 메소드가 있는데, 이 메소드는 파라미터로 arr를 받아서 프린트해 주면 []안에 프린트된다.
// 배열의 첫번째 요소에 저장된 값을 출력
// var num1 = 1의 num1과 arr[0]은 동일하다. // 1을 만들려면 var num1 = 1 이렇게 했어야 했는데, 연속적으로 배열을 만들어서 arr의 0번 방~4번 방까지 5개의 변수를 저장해서 꺼내 쓸 수 있게 된다.
// arr[0]은 하나의 변수로 취급할 수 있다.
// arr은 0~4번방(인덱스)까지 접근할 수 있다.
    println(arr[0])                     // arrayOf의 5개의 변수들에 접근하려면 그의 변수명 뒤에 인덱스(방 번호)를 써서 접근한다.
}

/*
--> 결과
[1, 2, 3, 4, 5]
1
*/

2. 배열을 사용하는 이유

  • 변수들을 각각 선언하면 반복적으로 변수에 접근하는 행위를 할 수 없다.
  • 배열이 없다면 점수를 저장하기 위해 score1, score2, score3 이런 식으로 변수를 만들어야 한다.
  • 배열을 사용한다면 scores로 점수들을 묶어 활용하면 효율적으로 코드를 작성할 수 있다.

3. 예시 코드

  • 국어점수를 배열로 묶어 모든 점수를 출력
 fun main() {
    var kors = arrayOf(90, 94, 96)
    for((idx, kor) in kors.withIndex()) {        // 반복문을 돌린다. kors 변수에 withIndex()라는 메소드를 호출하면 '인덱스(위치 정보)'와 '실제 값' 이 2개의 값을 하나로 묶어서 리턴해준다.
        println("${idx}번째 국어 점수는 ${kor}입니다")
    }
}

/*
--> 결과
0번째 국어 점수는 90입니다
1번째 국어 점수는 94입니다
2번째 국어 점수는 96입니다
*/

⭐️ withIndex()라는 메소드를 호출하면 '인덱스(위치 정보)'와 '실제 값' 이 2개의 값을 하나로 묶어서 리턴해준다.


🥜 컬렉션

1. 컬렉션이란?

  • 개발에 유용한 자료구조를 제공한다.
  • 코틀린에서는 리스트, 맵, 집합 자료구조를 지원한다.

2. - List의 활용

  • 리스트읽기 전용수정 가능한 종류로 구분할 수 있다.
  • 배열(array)와 달리 (연속적인 값을 저장할 수 있긴 하지만) 크기가 정해져있지 않아 동적으로 값을 추가할 수 있다.
// 1. 읽기 전용 리스트
// 0번, 1번, 2번 인덱스에 접근해서 값을 변경할 수 없다.(값1을 값5로 바꿀 수 없다.)
var scores1 = listOf(1,2,3)

// 2. 수정 가능 리스트
// 0번, 1번, 2번 인덱스에 접근해서 값을 변경할 수 있다.
var scores2 = mutableListOf(1,2,3)
scores2.set(인덱스,)    // 변수명.에 set()메소드를 불러서 값을 변경

// 수정 가능 리스트
// 0번, 1번, 2번 인덱스에 접근해서 값을 변경할 수 있다.
// array로 데이터들을 저장하는 ArrayList도 mutableListOf와 동일하게 사용할 수 있다.
// mutableListOf와 다르게 저장할 데이터의 자료형을 < > 안에 지정해야 사용할 수 있다.(array 형태 즉, 배열 형태로 차곡차곡 저장하기 때문에 실제로 코딩할 때는 ArrayList를 많이 사용한다.)
var scores3 = ArrayList<자료형>(1,2,3)
scores3.set(인덱스,)

3. - Map의 활용

  • 키와 값의 쌍으로 이루어진 자료형이다.
  • 읽기 전용과 수정 가능한 종류로 구분할 수 있다.
fun main() {
    // 1. 읽기 전용 맵
    // 변수명[키]로 데이터에 접근할 수 있다.
    var scoreInfo1 = mapOf("kor" to 94, "math" to 90, "eng" to 92)    // kor라는 키에 94라는 값을 맵핑한 것
    println(scoreInfo1["kor"])

    // 2. 수정 가능 맵
    // 변수명[키]로 데이터에 접근할 수 있다.
    var scoreInfo2 = mutableMapOf("kor" to 94, "math" to 90)
    scoreInfo2["eng"] = 92
    println(scoreInfo2["eng"])

    // 맵의 키와 값을 동시에 추출해서 효율적으로 사용할 수 있다.
    for((k,v) in scoreInfo2) {    // for문에서 in하고 맵 변수를 넣어주면 알아서 차곡차곡 하나씩 키와 값을 묶어서 리턴을 해주고, 한꺼번에 출력할 수 있다.
        println("${k}의 값은 ${v}입니다")
    }
}

/*
--> 결과
94
92
kor의 값은 94입니다
math의 값은 90입니다
eng의 값은 92입니다
*/

4. Set의 활용

▶️ 기본 활용

  • 은 순서가 존재하지 않고 중복 없이 데이터를 관리하는 집합 자료형이다.(마치 교집합, 차집합, 합집합 등의 느낌)
  • 읽기 전용과 수정 가능한 종류로 구분할 수 있다.
  • 다른 컬렉션들은 요소를 찾는데에 집중하지만, Set은 요소가 존재하는지에 집중한다.
  • 리스트나 맵을 이용해서 인덱스 정보를 활용한 탐색을 하지 않고 단지 존재하는 지만 보고싶다면 셋을 활용해서 conrain()메소드로 금방 찾을 수 있다.
fun main() {
//  1. 읽기 전용 Set
    var birdSet = setOf("닭", "참새", "비둘기")

//  2. 수정 가능 Set
//  var mutableBirdSet = mutableSetOf("닭", "참새", "비둘기")

//  mutableBirdSet.add("꿩")        // add와 remove를 사용할 수 있다.
//  mutableBirdSet.remove("꿩")

    println("집합의 크기는 ${birdSet.size}입니다")    // 앞으로 집합의 크기 설정을 많이 하게 될 것이다. 집합 변수명.size를 하면 크기를 리턴해준다.

    var findBird = readLine()!!    // 빨리 보기 위해 !!로 null이 아님을 보장

    if (birdSet.contains(findBird)) {    // contains()라는 메소드 사용
        println("${findBird}는 존재합니다.")
    } else {
        println("${findBird}는 존재하지 않습니다.")
    }
}

/*
--> 결과
집합의 크기는 3입니다
(입력)꿩
꿩는 존재하지 않습니다.
*/

▶️ 고급 활용

  • 교집합, 차집합, 합집합으로 간편하게 요소들을 추출할 수 있다.
fun main() {
    // 귀여운 새의 집합
    var birdSet = setOf("닭", "참새", "비둘기", "물오리")

    // 날수 있는 새의 집합
    var flyBirdSet = setOf("참새", "비둘기", "까치")

    // 모든 새의 집합 (합집합) : union()
    var unionBirdSet = birdSet.union(flyBirdSet)

    // 귀엽고 날수 있는 새의 집합 (교집합) : intersect()
    var intersectBirdSet = birdSet.intersect(flyBirdSet)

    // 귀여운 새들 중에서 날수 없는 새의 조합 (차집합) : subtract()
    var subtractBirdSet = birdSet.subtract(flyBirdSet)

    println("=====합집합=====")
    println("모든 새의 집합 : ${unionBirdSet}")

    println("=====교집합=====")
    println("귀엽고 날수있는 새의 집합 : ${intersectBirdSet}")

    println("=====차집합=====")
    println("귀엽고 날수없는 새의 집합 : ${subtractBirdSet}")
}

/*
--> 결과
=====합집합=====
모든 새의 집합 : [닭, 참새, 비둘기, 물오리, 까치]
=====교집합=====
귀엽고 날수있는 새의 집합 : [참새, 비둘기]
=====차집합=====
귀엽고 날수없는 새의 집합 : [닭, 물오리]
*/

5. 예시 코드

  • 학생 3명의 점수를 입력받아 평균점수를 출력하기위해 컬렉션을 활용해서 만들어보자.
fun main() {
    var students = mutableListOf<Student>()
    var averages = mutableMapOf<String, Int>()

    for (idx in 0..2) {            // 동적으로 학생들의 정보를 입력받음.(총 3명)
        println("학생의 이름을 입력하세요")
        var name = readLine()!!

        println("국어 점수를 입력하세요")
        var kor = readLine()!!.toInt()

        println("수학 점수를 입력하세요")
        var math = readLine()!!.toInt()

        println("영어 점수를 입력하세요")
        var eng = readLine()!!.toInt()

        var average = (kor + math + eng) / 3
        var tempStudent = Student(name, kor, math, eng)    // 학생의 정보를 Student클래스의 객체로 만들고 인스턴스화 함.

        students.add(tempStudent)                          // students 리스트에 동적으로 add해서 추가함.
        averages[name] = average                           // 그 학생의 이름을 키 값으로 해서 평균 점수를 저장.
    }

    for (student in students) {                            // students 리스트에서 하나씩 꺼내와서 그 사람의 평균 점수를 출력.
        var average = averages[student.name]
        student.displayInfo()
        println("평균점수는 ${average} 입니다")
    }
}

class Student(name: String, kor: Int, math: Int, eng: Int) {    // 주생성자를 통해 값을 받아옴.
    var name: String
    var kor: Int
    var math: Int
    var eng: Int

    init {
        this.name = name
        this.kor = kor
        this.math = math
        this.eng = eng
    }

    fun displayInfo() {
        println("이름: $name")
        println("국어: $kor")
        println("수학: $math")
        println("영어: $eng")
    }
}

/*
--> 결과
학생의 이름을 입력하세요
쵸파
국어 점수를 입력하세요
90
수학 점수를 입력하세요
75
영어 점수를 입력하세요
80
학생의 이름을 입력하세요
덕만
국어 점수를 입력하세요
50
수학 점수를 입력하세요
40
영어 점수를 입력하세요
65
학생의 이름을 입력하세요
딱지
국어 점수를 입력하세요
95
수학 점수를 입력하세요
100
영어 점수를 입력하세요
90
이름: 쵸파
국어: 90
수학: 75
영어: 80
평균점수는 81 입니다
이름: 덕만
국어: 50
수학: 40
영어: 65
평균점수는 51 입니다
이름: 딱지
국어: 95
수학: 100
영어: 90
평균점수는 95 입니다
*/

6. - 제네릭(Generic) (추가 지식)❓❓

  • 코드를 작성하다 보면 다양한 타입에 동일한 로직을 적용할 때가 많다.
  • 매번 Any타입으로 받는 것은 타입 안정성을 저하시킬 수 있다.
  • 클래스 내부에서 사용할 자료형을 인스턴스를 생성할 때 고정한다.
  • 컴파일 시간에 자료형을 검색해 적당한 자료형을 선택할 수 있도록 한다.
  • 객체 자료형의 안정성을 높이고, 형변환의 번거로움이 줄어든다.
fun <T> test(arr: Array<T>, data: T): Int {
    for(i in arr.indices) {
        if(arr[i] == data) return i
    }
    return -1
}

fun main() {
    val obj1: Array<String> = arrayOf("c", "java", "kotlin")

    val index = test<String>(obj1, "kotlin")
    println(index)
}
profile
코린이 강아지 집사🐶

0개의 댓글