Int와 Double같은 타입은 모두 하나의 변수에 하나의 값만 저장하도록 되어있는데,
프로그래밍을 하다보면 하나의 변수에 여러개의 값을 저장해야할때가 있다
이처럼 여러개의 값을 하나의 변수에 저장할수있도록 배열(Array)과 컬렉션(Collection)이라는 데이터 타입을 제공한다
# 배열
- 여러개의 값을 담을 수 있는 대표적인 자료형
- 배열 공간의 개수를 할당하거나, 초기화시에 데이터를 저장해주면 데이터의 개수만큼 배열의 크기가 결정됨
- 개수를 정해놓고 사용해야하며, 중간에 개수를 추가하거나 제거할 수 없다
var 변수 = Array(개수)
-> 배열은 다른 데이터 타입과 마찬가지로, 변수에 저장해서 사용할수있으며 위와같은 형태로 선언한다
var students = IntArray(10)
var longArray = LongArray(10)
var CharArray = CharArray(10)
var FloatArray = FloatArray(10)
var DoubleArray = DoubleArray(10)
-> 배열 객체는 Int, Long, Char 등과 같은 타입 뒤에 Array를 붙여서 만든다
- 첫번째 줄은 변수 students에 Int(정수형)공간을 10개 할당하라는 의미
- students라는 이름으로 정수형 데이터를 담을수있는 10개의 공간을 가진 배열이 만들어지고, 각 공간에는 아직 무슨값이 들어있는지 모름
- 인덱스를 사용해서, 10개의 공간을 가지는 위와 같은 배열의 인덱스는 0부터 시작해서 9에서 끝남(컴퓨터는 0을 첫번째로 인식함)
# 문자 배열에 빈공간 할당하기
- String은 Int, Double 등과 같은 기본 타입이 아니기 때문에 StringArray는 없지만, 다음과 같이 사용할 수 있다
var stringArray = Array(10, { item -> "" } )
-> 괄호안의 숫자인 10만 변경해서 사용하면, 그 숫자만큼 빈 문자열로 된 배열공간을 할당한다
# 값으로 배열공간 할당하기
- arrayOf 함수를 사용해서 String값을 직접 할당할수있다
var dayArray = arrayOf("MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN")
# 배열에 값 입력하기
- 배열을 선언한 변수명 옆에 대괄호 [ ] 를 사용하고, 대괄호안에 값을 저장할 위치의 인덱스 번호를 작성한다. 그리고 등호를 사용해서 값을 입력할 수 있다
배열명[인덱스] = 값
- set 함수도 사용할 수 있다
- set 함수에 인덱스와 값을 파라미터로 넘겨준다
배열명.set(인덱스, 값)
다음은 첫번째부터 열번째까지의 인덱스 값을 바꾸는 예제 코드이다
students[0] = 90
students.set(1, 91)
...
sutdents.set(8, 98)
students[9] = 99
-> students의 인덱스 0번째에 90을 넣고, 인덱스 1번째에는 91을 넣는다
-> students의 인덱스 8번째에 98을 넣고, 인덱스 9번째에는 99를 넣는다
# 여기서 잠깐!!
- 배열의 범위를 벗어난 인덱스에 값을 넣을 경우에는 어떻게 될까??
- 아래 예제와 같이, 10개의 공간이 할당된 배열에서 11번째에 해당하는 10번 인덱스에 값을 넣으려고하면, 범위를 넘어섰다는 Exception이 발생하고 프로그램이 종료된다
var intArray = IntArray(10)
intArray[10] = 100 // Exception 발생. intArray의 마지막 인덱스는 9입니다.
--> ArrayIndexOutOfBoundsException 발생
# 배열에 있는 값 꺼내기
- 저장할 때와 마찬가지로, 대괄호안에 인덱스를 입력해서 값을 가져올 수 있으며, get()을 이용할수도 있다
배열명[인덱스]
배열명.get(인덱스)
var seventhValue = intArray[6]
-> 배열 intArray의 일곱번째값을 seventhValue 변수에 저장한다
var tenthValue = intArray.get(9)
-> 배열 intArray의 열번째 값을 get함수를 사용해서 tenthValue변수에 저장한다
아래는 예제 전체 코드이다
package net.flow9.thisiskotlin.basicsyntax
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 1. 기본타입 배열 선언하기 - 각 기본타입별로 10개의 빈 공간이 할당된다
var students = IntArray(10)
var longArray = LongArray(10)
var CharArray = CharArray(10)
var FloatArray = FloatArray(10)
var DoubleArray = DoubleArray(10)
// arrayOf를 사용하면 선언과 동시에 값을 입력할 수 있다
var intArray = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// intArray 변수에는 1 부터 10까지의 값이 각각의 배열공간에 저장되어 있다
// 2. 문자열타입 배열 선언하기
var stringArray = Array(10, { item -> "" })
// arrayOf 함수로 값을 직접 입력해서 배열을 생성할 수 있다
var dayArray = arrayOf("MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN")
// 3. 앞에서 선언한 studens 변수에 값 넣기
// 가. 대괄호를 사용하는 방법
students[0] = 90
students[1] = 91
students[2] = 92
students[3] = 93
students[4] = 94
// 나. set 함수를 사용하는 방법
students.set(5, 95)
students.set(6, 96)
students.set(7, 97)
students.set(8, 98)
students.set(9, 99)
// 4. 값 변경해 보기
intArray[6] = 137 // 6번 인덱스인 7번째 값 7이 137로 변경된다
intArray.set(9, 200) // 9번 인덱스인 10번째 값 10이 200으로 변경된다
// 5. 배열 값 사용하기
var seventhValue = intArray[6]
Log.d("Array", "7번째 intArray의 값은 ${seventhValue}입니다")
var tenthValue = intArray.get(9)
Log.d("Array", "10번째 intArray의 값은 ${tenthValue}입니다")
Log.d("Array", "1번째 dayArray 값은 ${dayArray[0]}입니다")
Log.d("Array", "6번째 dayArray 값은 ${dayArray.get(5)}입니다")
}
}
/** [로그캣 출력 내용]
7번째 intArray의 값은 137입니다
10번째 intArray의 값은 200입니다
1번째 dayArray 값은 MON입니다
6번째 dayArray 값은 SAT입니다
*/
# 컬렉션
- 컬렉션(Collection)은 다른 이름으로는 "동적배열" 이라고도 한다
- 배열과는 다르게, 공간의 크기를 처음크기로 고정하지 않고, 임의의 개수를 담을 수 있기 때문이다
- 컬렉션은 크게 세가지로, 리스트(List), 맵(Map), 셋(Set) 이 있다
# 리스트(List)
- 리스트는 저장되는 데이터에 인덱스를 부여한 컬렉션이며, 중복된 값을 입력할수있다
- Kotlin에서 동적으로 리스트를 사용하기 위해서는 리스트 자료형 앞에 Mutable(뮤터블)이라는 접두어가 붙는다
- 예를 들면, mutableList, mutableMap, mutableSet 이 있다
- 배열과 같이 '데이터 타입Of" 형태로 사용할 수 있다
var list = mutableListOf("MON", "TUE", "WED")
# 여기서 잠깐!!
- Mutable(뮤터블)이란??
- Mutable(뮤터블)이란 "변할 수 있다" 라는 의미를 가지고 있다
- kotlin은 컬렉션 데이터 타입을 설계할때 모두 immutable(이뮤터블: 변할수없는)으로 설계했다. 그래서 기본 컬렉션인 리스트(List), 맵(Map), 셋(Set)은 모두 한번 입력된 값을 바꿀 수 없다
- 그래서 컬렉션의 원래 용도인 동적배열!! 로 사용하기 위해서는 Mutable(뮤터블)로 만들어진 데이터 타입을 사용해야한다
# 리스트 생성하기 : mutableListOf
- 다음과 같이 작성하면, 변수에 "MON", "TUE", "WED" 의 3개의 값을 가진 크기가 3인 동적 배열 리스트가 생성된다
var mutableList = mutableListOf("MON", "TUE", "WED)
# 리스트에 값 추가하기 : add
- add 함수를 사용해서 값을 추가할수있다
- 값이 추가되면, 동적으로 리스트의 공간이 자동으로 증가된다
mutableList.add("THU")
- add 함수를 사용하면, 입력될 위치인 인덱스를 따로 지정해주지 않아도 입력되는 순서대로 인덱스가 지정된다
-> "MON": [0], "TUE": [1], "WED": [2] --> "MON": [0], "TUE": [1], "WED": [2], "THU": [3]
# 리스트에 입력된 값 사용하기 : get
- get함수로 리스트에서 값을 꺼내서 사용할 수 있다
- 입력과는 다르게, 입력된 값을 사용할때는 인덱스를 지정해서 몇번째 값을 꺼낼것인지를 명시해야한다
var variable = mutableList.get(1)
-> 두번째 값을 꺼내서 variable이라는 변수에 저장한다
# 리스트값 수정하기 : set
- set함수를 사용해서 특정 인덱스의 값을 수정할 수 있다
mutalbeList.set(1, "수정")
-> 두번째 값을 "수정" 으로 수정했다
# 리스트에 입력된 값 제거하기 : removeAt
- removeAt 함수로 리스트에 입력된 값의 인덱스를 지정해서 삭제할 수 있다
mutableList.removeAt(1)
-> 두번째 값을 삭제했다
-> 두번째 값을 삭제하면, 세번째 값부터 인덱스가 하나씩 감소하면서 빈자리의 인덱스로 이동한다
-> "MON": [0], "TUE": [1], "WED": [2] --> "MON": [0], "WED": [1]
-> "TUE"가 삭제되면서 3번째값인 "WED"의 인덱스는 2에서 1로 바뀐다
# 빈 리스트 사용하기
- 아무것도 없는 빈 리스트를 생성하면, 앞으로 입력되는 값의 데이터타입을 알 수 없기 때문에 값의 타입을 추론할 수 없다
- 그래서 빈 컬렉션의 경우, 앞에서처럼 " 데이터타입Of "만으로는 생성되지 않고, 데이터타입을 직접적으로 알려주는 방법을 사용해야한다
var 변수명 = mutableListOf<컬렉션에 입력될 값의 타입>()
var stringList = mutableListOf<String>()
// 생성
var stringList = mutableListOf<String>()
// 입력
stringList.add("월")
stringList.add("화")
// 사용
Log.d("Collection", "stringList에 입력된 두 번째 값은 ${stringList.get(1)}입니다.")
// 수정
stringList.set(1, "수정된 값")
// 삭제
stringList.removeAt(1) // 두 번째 값이 삭제 됩니다.
-> 문자열로 된 빈 리스트를 생성하고 조작할 수 있다
# 여기서 잠깐!!
- 제네릭(Generic) 이란??
- 리스트 컬렉션을 생성하면서 < > 괄호를 사용하는데, 이 괄호를 제네릭(Generic)이라고 한다
- 제네릭(Generic)은 컬렉션이 사용하는 값의 타입을 지정하기 위한 도구이다
- kotlin에서 컬렉션은 제네릭을 사용하지 않으면 사용할 수 없다
- 단, 값으로 초기화할때는 입력되는 값으로 타입을 추론할 수 있기때문에 이때는 제네릭을 쓰지 않아도 생성할 수 있다
# 컬렉션 개수 가져오기 : size
- size 프로퍼티를 사용하면 컬렉션의 개수를 가져올 수 있다 (mutableList.size)
- 위에서 set, get 등은 "함수" 라고 하고, size는 "프로퍼티"라는 용어를 사용했는데, 이 둘을 구분하는 방법은 괄호의 유무이다
- 괄호가 있으면 -> 함수
- 괄호가 없으면 -> 프로퍼티
package net.flow9.thisiskotlin.basicsyntax
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 1. 값으로 컬렉션 생성하기
var mutableList = mutableListOf("MON", "TUE", "WED")
// 값 추가하기
mutableList.add("THU")
// 값 꺼내기
Log.d("Collection", "mutableList의 첫 번째 값은 ${mutableList.get(0)}입니다")
Log.d("Collection", "mutableList의 두 번째 값은 ${mutableList.get(1)}입니다")
// 2. 빈 컬렉션 생성하기기
var stringList = mutableListOf<String>() // 문자열로 된 빈 컬렉션 생성
// 값 추가하기
stringList.add("월")
stringList.add("화")
stringList.add("수")
// 값 변경하기
stringList.set(1, "날짜 변경")
// 사용
Log.d("Collection", "stringList에 입력된 두 번째 값은 ${stringList.get(1)}입니다")
// 삭제
stringList.removeAt(1) // 두 번째 값이 삭제된다.
Log.d("Collection", "stringList에 입력된 두 번째 값은 ${stringList.get(1)}입니다")
}
}
/** [로그캣 출력 내용]
mutableList의 첫 번째 값은 MON입니다
mutableList의 두 번째 값은 TUE입니다
stringList에 입력된 두 번째 값은 날짜 변경입니다
stringList에 입력된 두 번째 값은 수입니다
*/
-> 컬렉션 List를 사용한 예제이다
# 셋 (Set) - mutableSetOf
- set은 "중복을 허용하지 않는" 리스트이다
- 리스트와 유사한 구조이지만 인덱스로 조회할 수 없고, get함수도 지원하지 않는다
- String 타입의 값을 입력받기 위해 다음과 같이 선언할 수 있다
var set = mutableSetOf<String>()
# 빈 Set으로 초기화하고 값 입력하기
- set은 중복을 허용하지 않기 때문에 아래 코드를 보면, 네번째줄에서 입력한 "JAN"은 입력되지 않는다
var set = mutableSetOf<String>()
set.add("JAN")
set.add("FEB")
set.add("MAR")
set.add("JAN") // 동일한 값은 입력되지 않습니다.
# Set의 값 인덱싱?
- set은 인덱스로 조회하는 함수가 없기 때문에, 특정위치의 값을 사용할 수 없다
# Set의 값 삭제하기
- set은 값이 중복되지 않기 때문에, 아래와같이 값을 직접 입력하여 삭제해야된다
set.remove("FEB")
package net.flow9.thisiskotlin.basicsyntax
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 1. 셋 생성하고 값 추가하기
var set = mutableSetOf<String>()
set.add("JAN")
set.add("FEB")
set.add("MAR")
set.add("JAN") // 동일한 값은 입력되지 않는다.
// 2. 전체 데이터 출력해보기
Log.d("Collection", "Set 전체출력 = ${set}")
// 3. 특정 값 삭제하기
set.remove("FEB")
Log.d("Collection", "Set 전체출력 = ${set}")
}
}
/** [로그캣 출력 내용]
Set 전체출력 = [JAN, FEB, MAR]
Set 전체출력 = [JAN, MAR]
*/
-> 컬렉션 Set을 사용한 예제이다
# 맵(Map) - mutableMapOf
- Map은 키(key)와 값(Value)의 쌍으로 입력되는 컬렉션이다
- Map의 키는 리스트의 인덱스와 비슷한데, Map에서는 키를 직접 입력해야한다
- 제네릭으로 키와 값의 데이터타입을 지정해서 맵을 생성한다
var map = mutableMapOf<String, String>()
-> 키와 값의 타입을 모두 String으로 사용하기 위한 예제 코드이다
-> 인덱스에 해당하는 키를 직접 지정해서 사용해야한다
# 빈 Map으로 생성하고 값 추가하기
- 값을 추가하기 위해, 맵에서 제공되는 put함수를 사용해서 키와 값을 입력하면 된다
var map = mutableMapOf<String, String>()
map.put("key1", "value2")
map.put("key2", "value2")
map.put("key3", "value3")
-> 키와 값을 추가할때마다 리스트처럼 맵의 공간이 늘어난다
# Map 사용하기
- get 함수에 키를 직접 입력해서 값을 꺼낼 수 있다
Log.d("CollectionMap", "map에 입력된 key1의 값은 ${map.get("key1")}입니다.")
// [로그캣 출력 내용]
// map에 입력된 key1의 값은 value2입니다.
# Map 수정하기
- 입력할때와 같이 put함수를 사용해서 수정하는데 동일한 키를 가진값이 있으면, 키는 유지된 채로 그 값만 수정된다
map.put("key2", "수정")
-> 기존 "key2"의 값인 "value2"는 "수정"으로 바뀐다
# Map 삭제하기
- remove함수에 키를 입력해서 값을 삭제할 수 있다
- 리스트와는 다르게 인덱스에 해당하는 키의 값이 변경되지 않고, 그대로 유지된다
(삭제된다고해서 남아있는 인덱스의 값이 앞으로 옮겨가지 않음, 삭제되면 null값이 됨)
package net.flow9.thisiskotlin.basicsyntax
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 1. 맵 생성하기
var map = mutableMapOf<String, String>()
// 2. 값 넣기
map.put("키1", "값2")
map.put("키2", "값2")
map.put("키3", "값3")
// 3. 값 사용하기
var variable = map.get("키2")
Log.d("Collection", "키2의 값은 ${variable}입니다")
// 4. 값 수정하기
map.put("키2", "두 번째 값 수정")
Log.d("Collection", "키2의 값은 ${map.get("키2")}입니다")
// 5. 값 삭제하기
map.remove("키2")
// 5.1 없는 값을 불러오면 null값이 출력된다
Log.d("Collection", "키2의 값은 ${map.get("키2")}입니다")
}
}
/** [로그캣 출력 내용]
키2의 값은 값2입니다
키2의 값은 두 번째 값 수정입니다
키2의 값은 null입니다
*/
-> 컬렉션 Map을 사용한 예제
# 여기서 잠깐!!
- 컬렉션 값의 단위 = 엘리먼트
- 컬렉션에 입력되는 값 각각을 엘리먼트(Element) 라고 한다
- 값이라고 해도 되지만 맵을 지칭할 때 맵의 값(엘리먼트 자체)를 가리키는건지, 엘리먼트의 값(실제값)을 가리키는 건지 2개의 용어가 충돌할 수 있기 때문에 엘리먼트라고 이해하는것이 좋다
- 엘리먼트는 맵의 입력단위인 키와 값을 합친것을 말하는데, 이것은 리스트와 셋에서도 동일한 용어로 사용된다
- 즉, 리스트의 값 또한 엘리먼트라고 부른다
- -> 리스트 엘리먼트 = 리스트의 (값)
- -> 맵 엘리먼트 = 맵의 (키와 값)
# 이뮤터블 컬렉션 (Immutable Collection)
- kotlin은 일반 배열처럼 크기를 변경할 수 없으면서, 값 또한 변경할 수 없는 "이뮤터블 컬렉션"을 지원한다
- 이뮤터블 컬렉션은 다음과 같이 기존 컬렉션에서 mutable이라는 접두어가 제거된 형태로 사용된다
var list = listOf("1", "2")
- 불변형 컬렉션은 한번 입력된 값을 변경할 수 없기 때문에, add나 set함수는 지원하지 않고, 최초 입력된 값만을 사용할 수있다
- 배열과 다른 점은 크기뿐만 아니라, 값의 변경 또한 불가능하다는 것이다
- 즉, 불변형 컬렉션은 수정, 추가, 제거가 모두 안된다
var immutableList = listOf("JAN", "FEB", "MAR") // 생성
Log.d("Collection", "리스트의 두 번째 값은 ${immtuableList.get(1)}입니다.) // 사용
// [로그캣 출력 내용]
// 리스트의 두 번째 값은 FEB입니다.
# 그러면 이뮤터블 컬렉션은 언제 사용할 수 있을까??
- 일반변수 var과 읽기전용변수 val의 관계에서 이 사용법을 유추할 수 있는데, 기준이 되는 어떤 값의 모음을 하나의 변수에 저장할 필요가 있거나 또는 여러개의 값을 중간에 수정하지 않고 사용할 필요가 있을때 이뮤터블 컬렉션을 사용한다
- 대표적인 예로 요일 데이터가 있다
- -> 아래처럼 7개의 요일을 이뮤터블 리스트로 선언하면, 중간에 바뀌지 않기 때문에 계속 같은 값을 유지하면서 사용할 수 있다
var dayList = listOf("월", "화", "수", "목", "금", "토", "일)
'개발 노트 > Kotlin' 카테고리의 다른 글
[kotlin]함수 (0) | 2024.01.16 |
---|---|
[kotlin]반복문 (0) | 2024.01.16 |
[kotlin]조건문 (0) | 2024.01.16 |
[kotlin]변수 (0) | 2024.01.16 |
Log, Logcat (0) | 2024.01.16 |