본문 바로가기
Java/JAVA에 대하여

HashSet 내부

by lms0806 2022. 9. 24.
728x90
반응형

이클립스에서

HashSet<String> set = new HashSet<>();

을 선언하였을 떄, HashSet 부분을 'Ctrl + 클릭'을 통해서 확인했던 내용을 정리해보고자 적게 되었습니다.

HashSet을 활용하는데 어느 정도는 좀 더 알고 활용을 하자는 취지로 정리하였습니다.

 

public HashSet() {
	map = new HashMap<>();
}

가장 먼저 보이는 것을 보면, HashSet을 선언하면 HashMap<>();으로 선언하는 것을 볼 수 있습니다.

이는 추후에 나오는 부분을 보면 이해가 가능합니다.

 

public HashSet(Collection<? extends E> c) {
	map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
	addAll(c);
}

HashSet에 특정 Collection을 초기값으로 넣고 진행하여 사용할떄 선언됩니다.

ArrayList<String> arr = new ArrayList<>();
arr.add("a");
arr.add("b");
		
HashSet<String> set = new HashSet<>(arr);

이런식으로 선언할 경우 사용됩니다.

Collections을 사용하기 위한 충분한 공간을 저장하기 위해 Math.max((int) (c.size() / .75f) + 1, 16));을 사용한 후, addAll(c)를 통해 해당 Collections에 있는 모든 정보를 저장합니다.

 

public HashSet(int initialCapacity, float loadFactor) {
	map = new HashMap<>(initialCapacity, loadFactor);
}

해당 방식은 HashSet의 초기 크기값고, 해당 크기를 넘어갈 경우, 어느 정도로 더 크기를 둬서 저장을 할 수 있도록 공간을 준비합니다.

HashSet<String> set = new HashSet<>(1, 10);

해당 set의 크기는 1, 10, 100 순으로 10을 곱하면서 커집니다.

 

public HashSet(int initialCapacity) {
	map = new HashMap<>(initialCapacity);
}

이전 방식과는 비슷하지만 다른 방식으로, HashSet을 지정된 크기만큼 선언하여 사용됩니다. 이전 방식과 다른점으로는 load factor를 선언하지 않아서 0.75배수만큼 커지면서 공간을 확보하게 됩니다.

 

public Iterator<E> iterator() {
	return map.keySet().iterator();
}

Set 종류를 출력할 때 사용하는 Iterator입니다. 특별한 순서 없이, set의 방식대로 저장된 순서대로 값을 가지게 됩니다.

 

public int size() {
	return map.size();
}

set의 size를 반환합니다.

 

public boolean isEmpty() {
	return map.isEmpty();
}

해당 set이 비어있는지 여부를 boolean 타입으로 반환합니다.

 

public boolean contains(Object o) {
	return map.containsKey(o);
}

해당 set에 특정 값 o가 있는지 여부를 boolean 타입으로 반환합니다.

 

public boolean add(E e) {
	return map.put(e, PRESENT)==null;
}

앞에서 말씀드렸던 HashSet이 왜 map으로 선언되어 있는지를 알 수 있는 add 구문입니다.

set에 들어오는 변수를 map의 key값으로 넣고, value값에는 빈 object를 넣어 저장합니다.

HashMap의 내부 알고리즘 중 HashCode, equals를 비교하여 값을 넣게 됩니다.

만약 key값이 중복으로 존재한다면 반환하지 않습니다.

 

public boolean remove(Object o) {
	return map.remove(o)==PRESENT;
}

remove도 마찬가지로 HashMap의 remove의 결과값을 바탕으로 반환합니다.

 

public void clear() {
	map.clear();
}

clear()도 map의 clear()를 활용하여 set의 크기를 초기화 시킨후 반환하진 않습니다.

 

@SuppressWarnings("unchecked")
public Object clone() {
	try {
		HashSet<E> newSet = (HashSet<E>) super.clone();
		newSet.map = (HashMap<E, Object>) map.clone();
		return newSet;
	} catch (CloneNotSupportedException e) {
		throw new InternalError(e);
	}
}

새로운 해시SET을 만들어 준후 map의 clone()을 사용하여 복사해 줍니다.

여기서 CloneNotSupportedException을 해주는 이유는 clonable이 없는 경우을 예상해서 해주었습니다.

 

 

※ 후기

HashSet을 사용하면서 잘 안쓰던 방법(미리 크기를 정해준 후 선언)을 하지 않았었는데, 내부를 확인하면서 이러한 부분도 확인하게 되었습니다.

728x90
반응형

'Java > JAVA에 대하여' 카테고리의 다른 글

문자열 다루기  (0) 2024.04.14
LinkedHashSet에 대하여  (0) 2023.11.01
JAVA의 깊은 복사, 얕은 복사  (0) 2021.12.30
JVM이란  (0) 2021.12.25
JAVA 관련 deep한 내용들이 나와있는 사이트 정리  (0) 2021.12.24

댓글