[Kotlin] HashSet
Kotlin

[Kotlin] HashSet

반응형

HashSet이란?

Set은 중복을 허용하지 않는 자료구조로, 순서대로 입력되지 않고 일정하게 유지되지 않는게 특징이다.

HashSet은 null 요소도 허용한다. 가장 큰 특징은 중복을 허용하지 않는 것.


중복을 걸러내는 과정

HashSet은 객체를 저장하기 전에 먼저 객체의 hashCode() 메소드를 호출하여 해시코드를 얻어 낸 다음 저장되어 있는 개체들의 해시 코드와 비교한 뒤 같은 해시 코드가 있다면 equals() 메소드로 두 객체를 비교하여 같은 객체라면 중복 저장을 하지 않는다.

 


 

예제

fun main() {

    val hashSet = hashSetOf(1,2,3,4,5)

    hashSet.add(-1)
    hashSet.add(0)
    hashSet.add(-3)

    print(hashSet) // [-1, 0, 1, 2, -3, 3, 4, 5]

}

HashSet에서 -1, 0, -3을 요소로 추가했지만 뒤에 붙는 것이 아닌 어떤 것은 앞 쪽에 -3은 중간에 들어갔다. 

순서가 보장되지 않는다.

 

다음으로 LinkedHashSet에 값을 추가하는 예제를 보면

 

    val linkedHashSet = linkedSetOf(1,2,3,4,5)

    linkedHashSet.add(-1)
    linkedHashSet.add(0)
    linkedHashSet.add(-3)

    print(linkedHashSet) // [1, 2, 3, 4, 5, -1, 0, -3]

 

LinkedHashSet에서 -1, 0, -3을 요소로 add 했고, 순서대로 뒤에 붙는 것을 확인할 수 있다.

 


 

생성

 

개요

코틀린에서 Set은 setOf, MutableSet은 mutableSetOf 메소드를 사용해서 생성한다. 하지만, Set과 MutableSet은 인터페이스일 뿐이다. 이 인터페이스를 사용하기 위해서는 setOf나 mutableSetOf가 인터페이스를 구현하는 클래스의 인스턴스를 만들어야 한다.

 

    val set : Set<Int> = setOf(1,2,3)
    
    val mutableSet : MutableSet<Int> = mutableSetOf(1,2,3)

 

setOf 메소드와 mutableSetOf 메소드의 내부를 살펴보면

public fun <T> setOf(vararg elements: T): Set<T> = 
					if (elements.size > 0) elements.toSet() else emptySet()

public fun <T> Array<out T>.toSet(): Set<T> {
    return when (size) {
        0 -> emptySet()
        1 -> setOf(this[0])
        else -> toCollection(LinkedHashSet<T>(mapCapacity(size)))
    }
}

setOf는 toSet()을 통해 Set을 생성하고, toSet메소드는 LinkedHashSet을 이용하여 Set을 생성한다.

setOf를 통해 생성되는 Set은 LinkedHashSet이라는 것을 알 수 있다.

 

mutableSetOf 메소드를 살펴보면,

public fun <T> mutableSetOf(vararg elements: T): MutableSet<T> = 
					elements.toCollection(LinkedHashSet(mapCapacity(elements.size)))

mutableSetOf 또한 LinkedHashSet을 이용해 Set을 생성하는 것을 확인할 수 있다.

 

마지막으로 HashSet

val hashSet : HashSet<Int> = hashSetOf(1,2,3,4,5)

public fun <T> hashSetOf(vararg elements: T): HashSet<T> = 
				elements.toCollection(HashSet(mapCapacity(elements.size)))

hashSetOf() 메소드를 통해 Set을 생성하면 HashSet을 사용하면 된다.

HashSet이 가장 성능면에서는 좋을 것이다.

 


 

MutableSet 생성

자료구조가 LinkedHashSet인 MutableSet 생성

가장 대표적인 방법은 두가지가 있다.

  • mutableSetOf() 메소드 사용
val mutableSet : MutableSet<Int> = mutableSetOf(1,2,3)

 

  • Array를 toMutableSet() 메소드를 이용해 MutableSet으로 변환
    intArrayOf(1,2,3,4,5).toMutableSet()
    Array(5) { it }.toMutableSet()

자료구조가 HashSet인 MutableSet 생성

HashSet을 만들기 위해서는 직접 HashSet임을 지정해주어야 한다.

  • hashSetOf() 메소드를 이용해 생성
val hashSet : HashSet<Int> = hashSetOf(1,2,3,4,5)
  • Array를 toHashSet() 메소드를 이용해 MutableSet으로 변환
    val intSet : MutableSet<Int> = intArrayOf(1,2,3,5,6).toHashSet()
    val hashSet : MutableSet<Int> = Array(5) { it }.toHashSet()

 

 


값 접근 및 변경

값 접근

Set은 immutable 한 interface이므로, 값에 대한 접근만 가능하다. 따라서 여기서는 HashSet의 값을 접근하고 변경하는 방법을 설명한다.

 

    val hashSet : HashSet<Int> = hashSetOf(1,2,3,4,5)
    hashSet.forEach {
        print(it)  // 12345
    }
    
        for(i in hashSet) {
        print(i) // 12345
    }

 

값 변경하기

값 추가

  • 특정 element 추가하기 : 중복되는 값이 있는지 확인 후 값이 없는 경우에만 추가
    val hashSet : HashSet<Int> = hashSetOf(1,2,3,4,5)

    hashSet.add(3)
    hashSet.add(6)

    hashSet.forEach {
        print(it) // 123456
    }

 

  • Set 간에 plus 연산
    val hashSet1 : HashSet<Int> = hashSetOf(1,2)
    val hashSet2 : HashSet<Int> = hashSetOf(3,4,5)

    hashSet2 += hashSet1;

    hashSet2.forEach {
        print(it) // 12345
    }

 

값 제거

  • 특정 element 제거
    val hashSet : HashSet<Int> = hashSetOf(1,2,3)
    hashSet.remove(2)
    
    hashSet.forEach {
        print(it) // 13
    }

 

  • Set간에 뺄셈 연산 : Set 사이에서 operator function인 minus(-) 연산으로 제거가 가능
    val hashSet1 : HashSet<Int> = hashSetOf(1,2,3,4)
    val hashSet2 : HashSet<Int> = hashSetOf(3,4,5,6)

    hashSet2 -= hashSet1;

    hashSet2.forEach {
        print(it) // 56
    }

 

교집합

  • 집합이므로 교집합(intersect) 또한 가능하다
    val hashSet1 : HashSet<Int> = hashSetOf(1,2,3,4)
    val hashSet2 : HashSet<Int> = hashSetOf(3,4,5,6)

    val intersectSet = hashSet1.intersect(hashSet2)

    intersectSet.forEach {
        print(it) // 34
    }
반응형