Kotlin Programming Intermediate - 9

Beautify.log·2022년 1월 26일
0

Kotlin for Android

목록 보기
9/11
post-thumbnail

리스트는 배열과 다르게 길이에 대한 제약이 없으며 중간에 값이 빠지더라도 메모리를 차지하지 않습니다.

1억개의 값을 각각 배열과 리스트에 넣어주었을 때, 배열은 그 중에서 9천만개를 지운다면 천만개의 값과 9천만개의 빈공간이 남아 메모리를 차지합니다.

반면 리스트는 9천만개의 공간을 없애고 천만개만큼의 자리만 차지합니다.

이처럼 값의 삭제나 수정 등이 빈번하게 필요하다면 배열보다는 리스트를 사용하는 것이 좋습니다.

자바에서는 다음과 같이 리스트를 만들어주었습니다.

import java.util.*
public class Main {
	public static void main(String[] args) {

		List list = new ArrayList<>();
        
		// 값을 넣어줄 때
		list.add(123)

		// 값을 삭제할 때
		list.remove()

		// 값을 조회할 때
		list.get()

	}
}

Kotlin에서의 List란?


생성

코틀린에서는 listOf를 사용해서 리스트를 만들어줍니다.

fun main(args: Array<String>) {

	var numbers:List<Int> = listOf<Int>( 1, 2, 3, 4, 5 )

}

자료형이 List이고 제네릭에 Int를 선언했기 때문에 정수형만 올 수 있습니다.

이 리스트에 있는 값들을 하나씩 출력해주기 위해서는 for루프를 사용합니다.

fun main(args: Array<String>) {

	var numbers:List<Int> = listOf<Int>( 1, 2, 3, 4, 5 )
	for(num in numbers) {
		println("$num")
	}

}

문자열만 받는 리스트는 제네릭을 String으로 해주면 됩니다.

fun main(args: Array<String>) {

	var numbers:List<String> = listOf<String>( "one", "two", "three" )
	for(num in numbers) {
		println("$num")
	}

}

길이 확인

리스트의 크기는 size로 확인합니다.

fun main(args: Array<String>) {

	var numbers:List<Int> = listOf<Int>( 1, 2, 3, 4, 5 )
	println(numbers.size)

}

값 조회

값을 조회하는 방법은 다음과 같은 메서드를 사용하는 것입니다.

인덱스에 해당하는 값 가져오기

fun main(args: Array<String>) {

	var numbers:List<String> = listOf<String>( "one", "two", "three" )
	println(numbers.get(1))
	// 또는
	println(numbers[1])
    
	// 결과는 two

}

값에 대한 인덱스 가져오기

fun main(args: Array<String>) {

	var numbers:List<String> = listOf<String>( "one", "two", "three" )
	println(numbers.indexOf("two"))		// 1

}

값에 대한 인덱스와 값 한번에 출력하기

fun main(args: Array<String>) {

	val fruits = listOf("apple", "banana", "kiwi")
	for(item in fruits) println(item)
	for(index in fruits.indices) println("fruits[$index] : ${fruits[index]}")

}

인덱스 찾기

fun main(args: Array<String>) {

	val fruits = listOf("apple", "banana", "kiwi")
	
	var findIndex = -1		// 값을 못찾는 경우를 대비해 -1로 초기화
	for (i in 0..fruits.size - 1 step(1)) {
		if (fruits.get(i) === "banana") {
			findIndex = i
			break
		}
	}

	println(fruits[findIndex])

}

값 포함여부

리스트 내 조회할 값의 포함여부를 boolean으로 반환해줍니다.

fun main(args: Array<String>) {

	var numbers:List<String> = listOf<String>( "one", "two", "three" )
	println(numbers.contains("two"))	// true

}

여러가지 타입의 값 넣기

리스트에 정해진 자료형만 들어가는 것은 아닙니다.

fun main(args: Array<String>) {

	var mixedType = listOf("hello", 123, true, 123.456)
	for(m in mixedType) print("$m ")
	println()

}

제네릭을 선언해주지 않으면 다양한 자료형을 리스트에 담을 수 있습니다.

빈 리스트 생성

앞서 자바에서 리스트를 생성한것처럼 빈 리스트를 생성하고자 한다면

fun main(args: Array<String>) {

	var emptyList = emptyList<String>()

}

emptyList로 생성해줄 수 있습니다.

null이 아닌 element만 리스트에 담기

어떤 리스트에 null이 들어있다면 이 null을 필터링해서 null이 아닌 값만 담아줄 수 있는 리스트가 있는데, 바로 listOfNotNull입니다.

fun main(args: Array<String>) {

	val notNullList:List<Int> = listOfNotNull(2, 3, 4, null, 5, 7, null)    //이라면
	println(notNullList)    // null은 반영되지 않음
	println(notNullList[3])

}

ArrayList


물론 코틀린에서도 ArrayList를 사용할 수 있습니다.

listOf로 선언한 리스트를 값의 수정이나 삭제가 불가능한 배열과 비슷한 존재이기 때문에 값의 수정이나 삭제가 필요하다면 ArrayList를 사용해야 합니다.

선언

fun main(args: Array<String>) {

	val strList:ArrayList<String> = arrayListOf<String>("hello", "world", "success")

}

CRUD

자바의 ArrayList와 동일합니다.

fun main(args: Array<String>) {

	val strList:ArrayList<String> = arrayListOf<String>("hello", "world", "success")
	strList.add("kotlin")
	strList.get(1)	// hello
	strList.set(1, "hi")
	strList.remove(2)
}

가변형 리스트


개요

가변형 리스트는 지금부터 소개할 mutableList입니다. 반대말은 불변형 리스트이며 앞에서 살펴본 listOf로 선언된 리스트를 말합니다.

불변형 리스트는 가변형 리스트에 비해 리스트의 인덱스에 있는 원소에 접근하는 속도가 다소 빠릅니다.

한편 가변형 리스트는 새로운 원소를 추가할 때 추가적인 메모리 공간이 필요하기 때문에 메모리 효율 측면에서는 다소 떨어집니다.

그러므로 Kotlin에서 리스트를 사용할 때, 리스트를 수정해야한다면 불변형 리스트를 가변형 리스트로 바꿔주고 변경이 완료되었다면 다시 불변형 리스트로 바꿔주는 것이 좋습니다.

가변형 리스트의 CRUD

fun main(args: Array<String>) {

    // 선언
    val mutableListNames:MutableList<String> = mutableListOf<String>("kim", "lee", "yun")
    
    mutableListNames.add("park")    // insert
    println(mutableListNames)

    mutableListNames.removeAt(2)    // delete(인덱스로 삭제)
    println(mutableListNames)

    mutableListNames[0] = "choi"    // update
    // 또는 .set()
    println(mutableListNames)

}

불변형 리스트를 가변형 리스트로 바꿔주기

fun main(args: Array<String>) {

    // 가변형 리스트를
    var names:List<String> = listOf<String>("one", "two", "three")

    // 불변형 리스트로
    val newNames = names.toMutableList()
    newNames.add("five")
    println(newNames)

}

객체를 가변형 리스트로 관리하기

클래스 작성

class Duck(val name:String, val age:Int)

이 클래스를 리스트의 제네릭으로 지정해주고 값을 넣어보겠습니다.

fun main(args: Array<String>) {

    val list:MutableList<Duck> = mutableListOf()

    val duck = Duck("오리1", 2)
    list.add(duck)
    list.add(Duck("오리2", 2))
    list.add(Duck("오리3", 4))

    for (d in list) {
        println(d.name)
    }

}

Map


Map이란?

보통의 리스트는 인덱스당 하나의 값이 들어가는 구조라고 한다면 맵은 keyvalue가 한 쌍이 되어 하나의 인덱스를 차지합니다.

뿐만 아니라 값을 조회할 때 보통의 리스트는 인덱스를 기준으로 조회하지만 맵은 key값으로 value를 조회합니다.

fun main(args: Array<String>) {

    val langMap:Map<Int, String> = mapOf( 1001 to "kotlin", 1002 to "Java", 1003 to "react" )
    for ( (key, value) in langMap ){
        println("key=$key, value=$value")
    }
    println(langMap[1002])			// key가 1002인 값 조회
    println(langMap.get(1001))			// key가 1001인 값 조회
    println(langMap)				// {1001=kotlin, 1002=Java, 1003=react}
    println(langMap.keys)			// [1001, 1002, 1003] --> key값만 조회

}

langMapkeyvalue를 갖는 해쉬맵입니다. 리스트와 마찬가지로(listOf) mapOf로 선언되었기 때문에 불변형 Map입니다.

가변형 Map

가변형 Map은 가변형 List와 같은 개념입니다. 불변형 맵은 값의 수정, 삭제가 안되기 때문에 수정이나 삭제가 필요하다면 가변형 맵으로 바꿔주어야 합니다.

아예 가변형 맵으로 생성하는 방법도 있습니다. 그리고 두개의 해쉬맵을 합쳐줄 수도 있습니다.

fun main(args: Array<String>) {

    // 생성
    val capitalCityMap:MutableMap<String, String>
        = mutableMapOf("Korea" to "Seoul", "China" to "Beijing", "Japan" to "Tokyo")

    // 전체 출력
    println(capitalCityMap)		// {Korea=Seoul, China=Beijing, Japan=Tokyo}
    
    // key값만 출력
    println(capitalCityMap.keys)	// [Korea, China, Japan]
    
    // value만 출력
    println(capitalCityMap.values)	// [Seoul, Beijing, Tokyo]

    // key-value 추가
    capitalCityMap.put("UK", "London")
    
    // china 삭제
    capitalCityMap.remove("China")
    
    // 삭제 후 출력
    println(capitalCityMap)		// {Korea=Seoul, Japan=Tokyo, UK=London}



    // capitalCityMap과 addData 합치기
    val addData = mutableMapOf("USA" to "Washington", "India" to "NewDelhi")
    
    // capitalCityMap을 pullAll메서드로 addData와 합치기
    capitalCityMap.putAll(addData)
    
    // 출력
    println(capitalCityMap)		// {Korea=Seoul, Japan=Tokyo, UK=London, USA=Washington, India=NewDelhi}

}

정렬

해쉬맵에는 정렬 기능이 있습니다. 위에서 만들어준 capitalCityMap을 오름차순과 내림차순으로 각각 정렬해보겠습니다.

오름차순 정렬을 위해서는 sortedBy를 사용하며, 내림차순 정렬 시에는 sortedByDescending을 사용합니다.

fun main(args: Array<String>) {

    // 오름차순 정렬
    //var sortedByValue = capitalCityMap.toList().sortedBy { it.first }
    
    // 내림차순 정렬
    var sortedByValue = capitalCityMap.toList().sortedByDescending { it.first }
    println(sortedByValue)	// [(USA, Washington), (UK, London), (Korea, Seoul), (Japan, Tokyo), (India, NewDelhi)]

}

이 때 { it.first }iterator 즉 반복을 나타내며 첫번째 값을 기준으로 정렬을 반복하겠다는 의미가 됩니다.

profile
tried ? drinkCoffee : keepGoing;

0개의 댓글