[Kotlin/코틀린] 9. 배열(Array), 컬렉션(List, Map, Set), Single-expression function

2023. 12. 19. 06:56스파르타/Kotlin

 

4주차 '객체지향 프로그래밍의 심화' 강의 내용 정리

 

9-1. 배열

 

배열은 동일한 데이터 타입을 가진 여러 요소를 저장하는 자료 구조이다.

일반적으로 변수를 선언하면 코틀린은 랜덤으로 생성한다.

변수의 위치정보가 연속적이지 않기 때문에 순서가 없다.

코틀린에서 배열을 선언하고 초기화하는 방법은 다양하다.

arrayOf는 코틀린에서 배열을 생성하고 초기화하는 함수 중 하나이다.

 

 

 

 

실습 예제

arrayOf 메소드 호출

// arrayOf메소드를 호출하면 배열을 리턴해줍니다
// 1,2,3,4,5 각각을 저장한 변수 5개를 배열형태로 arr에 저장합니다
var arr = arrayOf(1,2,3,4,5)

// 배열요소를 모두 출력합니다
println(Arrays.toString(arr))

// 배열의 첫번째 요소에 저장된 값을 출력합니다
// var num1 = 1의 num1과 arr[0]은 동일합니다
// arr[0]은 하나의 변수로 취급할 수 있습니다
// arr은 0~4번방(인덱스)까지 접근할 수 있습니다
println(arr[0])

 

 

 

 

배열이 필요한 이유

변수들을 각각 선언하면 반복적으로 변수에 접근하는 행위를 할 수 없다.

배열이 없다면 점수를 저장하기 위해 score1, score2, score3 이렇게 변수를 만들어야 한다.

배열을 사용한다면 scores로 점수들을 묶어 활용하면 효율적으로 코드를 작성할 수 있다.

 

 

 

 

 

실습 예제 2

fun main() {
    var kors = arrayOf(90, 94, 96)
    for((idx, kor) in kors.withIndex()) {
        println("${idx}번째 국어 점수는 ${kor}입니다")
    }
}

 

withIndex()라는 메소드를 호출하게 되면 두 개의 값을 하나로 묶어서 리턴해준다.

첫번째는 idx (인덱스) 값, 두번째는 kor (실제) 값

 

 

실습 예제 2 실행결과

 

0번째, 1번째, 2번째 국어 점수가 출력된다.

 

 

 


 

 

9-2. 컬렉션

개발에 유용한 자료구조를 제공하는 제공한다.

코틀린에서는 리스트(list), 맵(map), 집합 자료구조를 지원한다.

 

 

 

 

 

 

list 실습 예제

리스트(list) 는 읽기 전용과 수정 가능한 종류로 구분할 수 있다.

배열(array)과 달리 크기가 정해져있지 않아 동적으로 값을 추가할 수 있다.

// 읽기전용 리스트입니다
// 0번, 1번, 2번 인덱스에 접근해서 값을 변경할 수 없습니다
var scores1 = listOf(값1, 값2, 값3)

// 수정가능 리스트입니다
// 0번, 1번, 2번 인덱스에 접근해서 값을 변경할 수 있습니다
var scores2 = mutableListOf(값1, 값2, 값3)
scores2.set(인덱스, 값)

// 수정가능 리스트입니다
// 0번, 1번, 2번 인덱스에 접근해서 값을 변경할 수 있습니다
// array로 데이터들을 저장하는 ArrayList도 mutableListOf와 동일하게 사용할 수 있어요
// 저장할 데이터의 자료형을 < > 안에 지정해야 사용할 수 있어요
var scores3 = ArrayList<자료형>(값1, 값2, 값3)
scores3.set(인덱스, 값)

 

읽기 전용 리스트는 listOf 로 만들고,

(값1, 값2, 값3)을 넣어서 scores1 이라는 리스트를 만들었다.

 

수정 가능 리스트는 mutableListOf 로 만들고,

(값1, 값2, 값3)을 수정하기 위해 [이름.set] 이라는 메소드를 불러서

(인덱스, 값) 몇 번째 인덱스에 값을 바꾸겠다고 수정하면 된다.

 

수정 가능 리스트는 ArrayList 도 사용할 수 있는데,

mutableListOf 와는 달리 내부에 배열 형태로 차곡차곡 저장한다.

실제 코딩을 하게 되면 ArrayList 형태를 자주 쓰게 된다.

사용하는 방식은 mutableListOf 와 동일하다.

 

 

 

 

 

 

map 실습 예제

맵(map) 은 읽기 전용과 수정 가능한 종류로 구분할 수 있다.

맵(map) 은 키와 값의 쌍으로 이루어진 자료형이라고 할 수 있다.

// 읽기전용 맵입니다
// 변수명[키]로 데이터에 접근할 수 있습니다
var scoreInfo1 = mapOf("kor" to 94, "math" to 90, "eng" to 92)
println(scoreInfo1["kor"])

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

// 맵의 키와 값을 동시에 추출해서 사용할 수 있습니다
for((k,v) in scoreInfo2) {
    println("${k}의 값은 ${v}입니다")
}

 

읽기 전용 맵은 mapOf 로 만들고,

수정 가능 맵은 mutableMapOf 로 만든다.

for 문에서 효율적으로 탐색하기 위해서 in 다음에 맵 변수를 넣어주면 println 으로 한 번에 출력이 가능하다.

 

 

 

 

 

 

 

 

 

Set 실습 예제

셋(Set) 은 읽기 전용과 수정 가능한 종류로 구분할 수 있다.

셋(Set)은 순서가 존재하지 않고 중복없이 데이터를 관리하는 집합 자료형이다.

다른 컬렉션들은 요소를 찾는데 집중하지만, Set은 요소가 존재하는 지에 대해 집중한다.

//  읽기전용 Set입니다.
var birdSet = setOf("닭", "참새", "비둘기")

//  수정가능 Set입니다.
//  var mutableBirdSet = mutableSetOf("닭", "참새", "비둘기")
//  mutableBirdSet.add("꿩")
//  mutableBirdSet.remove("꿩")
println("집합의 크기는 ${birdSet.size} 입니다")

var findBird = readLine()!!

if(birdSet.contains(findBird)) {
    println("${findBird} 종류는 존재합니다.")
} else {
    println("${findBird}는 존재하지 않습니다.")
}

 

읽기 전용 맵은  setOf 로 만들고,

수정 가능 맵은 mutableSetOf 로 만든다.

mutableSetOf 의 경우 add 나 remove 를 사용한다.

집합 변수.size 를 하면 크기를 리턴해준다.

 

 

 

 

Set 실습 예제 2

교집합, 차집합, 합집합으로 간편하게 요소들을 추출할 수 있다.

//  읽기전용 Set입니다.
// 귀여운 새의 집합
var birdSet = setOf("닭", "참새", "비둘기", "물오리")

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

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

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

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

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

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

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

 

합집합은 변수명.union 을 통해 합칠 수 있다.

변수명.intersect 를 통해 겹치는 교집합을 찾을 수 있다.

변수명.subtract 를 통해 차집합으로 나타낼 수 있다.

 

 

 

 

 

컬렉션을 활용한 실습 예제

학생 3명의 점수를 입력받아 평균점수를 출력한다.

fun main() {
    var students = mutableListOf<Student>()
    var averages = mutableMapOf<String, Int>()

    for(idx in 0..2) {
        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)

        students.add(tempStudent)
        averages[name] = average
    }

    for(student in 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")
    }
}

 

 

 


 

 

9-3. Single-expression function

람다식을 이용해서 메소드를 간결하게 정의할 수 있다.

자바 8과 동일하게 코틀린도 람다식을 지원한다.

하나의 메소드를 간결하게 표현할 수 있는 방법이다.

 

 

람다식의 기본 구조

{매개변수1, 매개변수2... ->
    코드
}

 

 

 

 

실습 예제 1

세 개의 숫자의 평균을 리턴해주는 함수를 람다식으로 정의한다.

fun add(num1:Int, num2:Int, num3:Int) = (num1+num2+num3)/3

 

 

 

 

 

실습 예제 2

메소드를 선언하지 않고 로직을 저장할 수 있다.

var add = {num1: Int, num2: Int, num3: Int -> (num1+num2+num3) / 3}
println("평균값은 ${add(10,20,30)}입니다")

 

화살표 -> 를 통해서 람다식으로 쉽게 정의했다.

정의한 람다식을 add 라고 정했다.