대용량 데이터 자동화 체계 구축을 진행하면서 Set(HashSet) 자료구조를 활용하였는데, 여기서 사용하는 Equals와 String의 Equals는 완전히 다른 개념이라는 것을 알게되었다.
이 내용을 향후에 많이 활용할 수 있고 실무적으로 꽤 중요한 의미를 지닐 것으로 판단하여 공부한 내용을 기록한다.
비교대상의 컬럼명을 입력받고, 그 대상의 데이터를 Set에 할당하면서 중복여부를 검사하는 로직을 구성하였다.
if(targetColumnIndex == -1){
throw new RuntimeException("'설비코드' 컬럼이 존재하지 않습니다. 설비컬럼 존재여부를 먼저 확인하십시오.'");
}
String value = currentRow.getOrDefault(targetColumnIndex, "").trim();
if(valueSet.contains(value)){
resultList.add(value);
System.out.println(rowNum + 1 + "행 데이터 중복 발생");
System.out.println("["+ value + "] 설비코드가 중복됩니다.");
}
valueSet.add(value);
이때 Set에 value를 넣을때마다 중복검사를 "contains"를 통해 진행한다.
이 contains는 단순 문자열의 포함여부가 아니라, Set에 넣은 값이 있는지 없는지 존재여부를 판단하기 위함으로 "key"의 존재여부를 검사하는 과정으로 봐야 한다.
if(targetColumnIndex == -1){
throw new RuntimeException("'설비코드' 컬럼이 존재하지 않습니다. 설비컬럼 존재여부를 먼저 확인하십시오.'");
}
String value = currentRow.getOrDefault(targetColumnIndex, "").trim();
if(valueSet.equals(value)){
resultList.add(value);
System.out.println(rowNum + 1 + "행 데이터 중복 발생");
System.out.println("["+ value + "] 설비코드가 중복됩니다.");
}
valueSet.add(value);
위 검수처럼 "equals"로 중복검사를 진행한다면 key값의 존재여부가 아닌, "객체 동등성"으로 판단하므로 검수에 걸리는 경우가 완전히 없어진다.
**이때 중요한 점:
사용자 입장에서는 Set을 Contains정도만 사용하고 Equals는 이론적으로 굳이 필요없다.
어차피 Set에 들어가는 데이터들은 중복을 허용하지 않으므로 객체동등성 비교가 무의미하기 때문이다.
이에 대해 알아본 바로는 "내부적으로 Set 알고리즘이 중복검사를 할때 Equals 메소드를 사용"하기 때문이다.
실제로도 contains의 과정을 내부적으로 살펴보면 파악이 가능하다.
public boolean containsKey(Object key) {
return getNode(key) != null;
}
final Node<K,V> getNode(Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n, hash; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & (hash = hash(key))]) != null) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
위 로직처럼 내부적으로 equals를 사용하여 객체동등성 비교 과정까지 진행하는데, 이때 equals를 사용하기 위해 제공하는 것으로 보이며, 이 메소드를 다른 자료구조에서도 동일하게 사용하므로 클린 코드 관점에서 해당 로직을 제공하고 있는 것으로 보였다.
사용자 입장에서는 Contains만 사용하면 되지만, 내부적으로 String과 다소 차이점이 있고 헷갈릴 수 있는 부분이기에 정리해놓는다.