자바 집합 에서 contains 방법의 효율 비교 분석
Java 집합 List,Set 에는 집합 에 있 는 요소 의 존재 여 부 를 판단 하 는 방법 contains(Object o)가 있 습 니 다.Map 에는 key 및 value 의 존재 여 부 를 판단 하 는 방법 인 containsKey(Object key)와 containsValue(Object value)가 있 습 니 다.
1.ArrayList
ArrayList 에서 contains 방법 은 list 의 요 소 를 옮 겨 다 니 며=또는 equals 를 이용 하여 목표 요소 가 존재 하 는 지 여 부 를 판단 하고 복잡 도 는 O(N)입 니 다.
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
2.HashSetHashSet 에 있 는 요 소 는 Key 형식 으로 HashMap 에 저장 되 어 있 으 며 요소 가 존재 하 는 지 여 부 를 판단 하 는 것 은 대응 하 는 Map 에 key 가 존재 하 는 지 여 부 를 판단 하 는 것 입 니 다.
HashSet:
private transient HashMap<E,Object> map; // transient, , 。
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
public boolean contains(Object o) {
return map.containsKey(o);
}
3.HashMapHashMap 에는 두 가지 contains 방법 이 있 습 니 다.하 나 는 key 가 존재 하 는 지,하 나 는 value 가 존재 하 는 지 판단 합 니 다.
HashMap 의 바 텀 은 주로 배열 과 링크(산 목록 또는 해시 표 라 고 함)를 바탕 으로 이 루어 집 니 다.이 는 상당히 빠 른 조회 속 도 를 가 진 이 유 는 해시 코드 를 계산 하여 저장 위 치 를 결정 하기 때 문 입 니 다.
그래서 containskey 는 key 의 해시 값 을 통 해 key 가 존재 하 는 지 직접 찾 습 니 다.시간 복잡 도 는 O(1)이 고 응답 하 는 HashSet 에서 요 소 를 찾 는 시간 복잡 도 는 O(1)입 니 다.
contains Value 방법 에 대해 map 에 value 가 존재 하 는 지 판단 하 는 방법 은 map 에 있 는 Node 배열 을 옮 겨 다 니 며 존재 하 는 지 판단 하 는 것 입 니 다.
transient Node<K,V>[] table;
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != 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;
}
public boolean containsValue(Object value) {
Node<K,V>[] tab; V v;
if ((tab = table) != null && size > 0) {
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next) {
if ((v = e.value) == value ||
(value != null && value.equals(v)))
return true;
}
}
}
return false;
}
4.총화각 방법의 시간 복잡 도 를 집합 하 다.
contains
containskey
containsValue
ArrayList
O(N)
HashSet
O(1)
HashKey
O(1)
O(N)
이런 기술 세부 사항 에 대해 평소에 주의 하고 축적 하 며 계속 공부 하고 기록 하 며 실제 개발 에 응용 하여 운영 효율 을 계속 향상 시 켜 야 한다.후속 적 으로 도 이런 기술 세부 사항 을 기록 하여 일상적인 개발 에서 활용 할 것 이다.
보충:Array List 의 contains 방법의 효율 은 과연 높 지 않다.
코드 보 세 요~
이전에 한 항목 에서 데이터 베 이 스 는 40 여 만 개의 데 이 터 를 추출 한 다음 에 csv 파일 에서 약 40 여 만 개의 데 이 터 를 추출 하여 비교 분석 하기 전에 코드 는 다음 과 같다.
List<String> keys = new ArrayList<String>();
int isize = msTaiyousr.size();
for (int i=0;i<isize;i++) {
Map<String, Object> msyaiyousr = msTaiyousr.get(i);
String id = (String) msyaiyousr.get("taiyousrid");
String usrtorokukbn = (String) msyaiyousr.get("usrtorokukbn");
keys.add(usrtorokukbn+":"+id);
}
int jsize = wkTaiyousr.size();
for (int j=0;j<jsize;j++) {
Map<String, Object> wktaiyousr = wkTaiyousr.get(j);
String id = (String) wktaiyousr.get("taiyousrid");
String usrtorokukbn = (String) wktaiyousr.get("usrtorokukbn");
if (keys.contains(usrtorokukbn+":"+id)) {
updateList.add(wktaiyousr);
} else {
insertList.add(wktaiyousr);
}
}
두 번 째 for 순환 은 Array List 의 contains 방법 을 사 용 했 기 때문에 두 번 째 for 순환 을 마치 고 12 분 정도 사 용 했 습 니 다.제 하루,첫 번 째 순환 은 1 초 도 안 됩 니 다.그리고 ArrayList 코드 대신 HashSet 을 사 용 했 습 니 다.다음 과 같 습 니 다.
Set<String> keys = new HashSet<String>();
int isize = msTaiyousr.size();
for (int i=0;i<isize;i++) {
Map<String, Object> msyaiyousr = msTaiyousr.get(i);
String id = (String) msyaiyousr.get("taiyousrid");
String usrtorokukbn = (String) msyaiyousr.get("usrtorokukbn");
keys.add(usrtorokukbn+":"+id);
}
int jsize = wkTaiyousr.size();
for (int j=0;j<jsize;j++) {
Map<String, Object> wktaiyousr = wkTaiyousr.get(j);
String id = (String) wktaiyousr.get("taiyousrid");
String usrtorokukbn = (String) wktaiyousr.get("usrtorokukbn");
if (keys.contains(usrtorokukbn+":"+id)) {
updateList.add(wktaiyousr);
} else {
insertList.add(wktaiyousr);
}
}
결 과 는 1 초도 안 돼 두 for 순환 이 순식간에 끝났다.역시 빅 데 이 터 는 Array List 의 contains 방법 을 사용 하지 말고 HashSet 로 바 꾸 세 요.이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.