JAVA 교체 기 깊이 이해
8986 단어 JAVA
개술
자바 집합 프레임 의 집합 류 를 우 리 는 때때로 용기 라 고 부른다.용기 의 종 류 는 여러 가지 가 있 습 니 다.예 를 들 어 Array List,LinkedList,HashSet...............................................................링크 드 리스트 는 링크 구조 입 니 다.HashSet 은 해시 표 에 의존 하 며 모든 용기 에는 자신 만 의 데이터 구조 가 있다.
용기 의 내부 구조 가 다 르 기 때문에 한 용기 의 요 소 를 어떻게 옮 겨 다 녀 야 할 지 모 를 때 가 많 습 니 다.그래서 용기 내 요소 에 대한 조작 을 더욱 간단하게 하기 위해 자바 는 교체 기 모드 를 도입 하 였 습 니 다!
방문 논 리 를 서로 다른 유형의 집합 류 에서 추출 하여 외부 로 집합 하 는 내부 구 조 를 노출 시 키 지 않도록 한다.
배열 에 대해 우 리 는 아래 표 시 를 사용 하여 처리 합 니 다.
1 int array[] = new int[3];
2 for (int i = 0; i < array.length; i++) {
3 System.out.println(array[i]);
4 }
Array List 처리
1 List list = new ArrayList();
2 for(int i = 0 ; i < list.size() ; i++){
3 String string = list.get(i);
4 }
이 두 가지 방식 에 대해 우 리 는 항상 그의 내부 구 조 를 알 고 방문 코드 와 집합 자체 가 밀접 하 게 결합 되 어 방문 논 리 를 집합 류 와 클 라 이언 트 코드 에서 분리 할 수 없다.서로 다른 집합 은 서로 다른 옮 겨 다 니 는 방법 에 대응 하여 클 라 이언 트 코드 를 재 활용 할 수 없습니다.실제 응용 에서 위의 두 집합 을 어떻게 통합 하 는 지 는 상당히 번거롭다.그래서 Iterator 가 있 습 니 다.항상 같은 논리 로 집합 합 니 다.클 라 이언 트 자체 가 집합 한 내부 구 조 를 유지 할 필요 가 없고 모든 내부 상 태 는 Iterator 가 유지 합 니 다.클 라 이언 트 는 집합 과 직접 접촉 하지 않 고 Iterator 가 앞으로 나 아 가 는 명령 을 보 내 면 집합 을 옮 겨 다 닐 수 있 습 니 다.
1.java.util.Iterator
자바 의 Iterator 인터페이스 가 어떻게 실현 되 는 지 살 펴 보 자.
자바 에서 Iterator 는 하나의 인터페이스 로 교체 의 기본 규칙 만 제공 합 니 다.JDK 에 서 는 Collection 을 교체 하 는 교체 기 라 고 정의 합 니 다.교체 기 는 자바 Collection Framework 의 Enumeration 을 대체 했다.교체 기 는 매 거 진 것 과 두 가지 가 다르다.
1.교체 기 는 교체 기간 에 집합 에서 원 소 를 제거 할 수 있다.
2.방법 명 이 개선 되 었 고 Enumeration 의 방법 명 이 비교적 길다.
그 인터페이스 정 의 는 다음 과 같다.
package java.util;
public interface Iterator {
boolean hasNext();//
E next();//
void remove();//
}
2.Iterable
자바 에 서 는 Iterable 인터페이스 도 제공 합 니 다.Iterable 인터페이스 가 실 현 된 후의 기능 은'되 돌아 가기'의 교체 기 입 니 다.우 리 는 이 인터페이스의 하위 인 터 페 이 스 를 자주 실현 합 니 다.Collection,List,Set 등 이 있 습 니 다.이 인터페이스의 iterator()방법 은 표준 Iterator 로 되 돌아 갑 니 다.Iterable 인터페이스 허용 대상 이 Foreach 문장의 목표 가 되도록 합 니 다.foreach 문 구 를 통 해 바 텀 시퀀스 를 옮 겨 다 닐 수 있 습 니 다.
Iterable 인 터 페 이 스 는 Iterator 대상 을 만 들 수 있 는 방법 을 포함 하고 Iterable 은 foreach 에 의 해 시퀀스 에서 이동 합 니 다.따라서 Iterable 인 터 페 이 스 를 실현 하 는 클래스 를 만 들 면 foreach 에 사용 할 수 있 습 니 다.
Iterable 인터페이스의 구체 적 인 실현:
Package java.lang;
import java.util.Iterator;
public interface Iterable {
Iterator iterator();
}
교체 기 를 사용 하여 집합 을 옮 겨 다 니 기:
1 public static void main(String[] args) {
2 List list = new ArrayList();
3 list.add(" 1");
4 list.add(" 2");
5 list.add(" 3");
6 list.add(" 4");
7
8 List linkList = new LinkedList();
9 linkList.add("link1");
10 linkList.add("link2");
11 linkList.add("link3");
12 linkList.add("link4");
13
14 Set set = new HashSet();
15 set.add("set1");
16 set.add("set2");
17 set.add("set3");
18 set.add("set4");
19 // ArrayList
20 Iterator listIt = list.iterator();
21 while(listIt.hasNext()){
22 System.out.println(listIt.next());
23 }
24 // Set
25 Iterator setIt = set.iterator();
26 while(setIt.hasNext()){
27 System.out.println(listIt.next());
28 }
29 // LinkedList
30 Iterator linkIt = linkList.iterator();
31 while(linkIt.hasNext()){
32 System.out.println(listIt.next());
33 }
34 }
foreach 를 사용 하여 집합 을 옮 겨 다 니 기:
List list = new ArrayList();
list.add(" 1");
list.add(" 2");
list.add(" 3");
list.add(" 4");
for (String string : list) {
System.out.println(string);
}
이 를 통 해 알 수 있 듯 이 foreach 를 사용 하여 집합 을 옮 겨 다 니 는 장점 은 코드 가 더욱 간결 하고 실수 하기 쉽 지 않 으 며 아래 표 시 된 시작 값 과 종료 값 에 관심 을 가지 지 않 아 도 된다 는 것 이다.
3.Iterator 를 옮 겨 다 닐 때 집합 에 있 는 요 소 를 삭제 할 수 없습니다.
Iterator 를 사용 할 때 옮 겨 다 니 는 용기 의 크기 구 조 를 바 꾸 는 작업 을 금지 합 니 다.예 를 들 어 Iterator 를 사용 하여 교체 할 때 집합 에 add,remove 작업 을 하면 Concurrent ModificationException 이상 이 발생 합 니 다.
1 List list = new ArrayList();
2 list.add(" 1");
3 list.add(" 2");
4 list.add(" 3");
5 list.add(" 4");
6
7 // ArrayList
8 Iterator listIt = list.iterator();
9 while(listIt.hasNext()){
10 Object obj = listIt.next();
11 if(obj.equals(" 3")){
12 list.remove(obj);
13 }
14 }
교체 하기 전에 교체 기 는 list.itertor()를 통 해 만 들 어 졌 기 때문에 교체 과정 에서 list 에 대해 용기 크기 를 바 꾸 는 작업 을 하면 자바 가 이상 을 줄 수 있 습 니 다.이 때 Iterator 대상 이 list 의 변 화 를 주동 적 으로 동기 화 할 수 없 기 때문에 자바 는 이러한 조작 을 하 는 것 이 스 레 드 가 안전 하지 않다 고 생각 하고 선의 의 알림 을 줄 것 입 니 다(Concurrent ModificationException 이상 을 던 집 니 다)
Iterator 의 실현 소스 코드:
1 private class Itr implements Iterator {
2 int cursor; // index of next element to return
3 int lastRet = -1; // index of last element returned; -1 if no such
4 int expectedModCount = modCount;
5
6 public boolean hasNext() {
7 return cursor != size;
8 }
9
10 @SuppressWarnings("unchecked")
11 public E next() {
12 checkForComodification();
13 int i = cursor;
14 if (i >= size)
15 throw new NoSuchElementException();
16 Object[] elementData = ArrayList.this.elementData;
17 if (i >= elementData.length)
18 throw new ConcurrentModificationException();
19 cursor = i + 1;
20 return (E) elementData[lastRet = i];
21 }
22
23 public void remove() {
24 if (lastRet < 0)
25 throw new IllegalStateException();
26 checkForComodification();
27
28 try {
29 ArrayList.this.remove(lastRet);
30 cursor = lastRet;
31 lastRet = -1;
32 expectedModCount = modCount;
33 } catch (IndexOutOfBoundsException ex) {
34 throw new ConcurrentModificationException();
35 }
36 }
37
38 final void checkForComodification() {
39 if (modCount != expectedModCount)
40 throw new ConcurrentModificationException();
41 }
42 }
원본 코드 를 확인 한 결과 원래 검 사 를 하고 이상 을 던 지 는 것 은 checkForComodification()방법 입 니 다.Array List 에서 modCount 는 현재 집합 한 버 전 번호 로 수정(추가,삭제)집합 할 때마다 1 을 추가 합 니 다.expected ModCount 는 현재 교체 기의 버 전 번호 로 교체 기 를 예화 할 때 modCount 로 초기 화 합 니 다.checkForComodification()방법 에서 modCount 의 값 과 expected ModCount 의 값 이 같은 지 검증 하 는 것 을 보 았 습 니 다.그래서 Array List.add()나 Array List.remove()를 호출 했 을 때 modCount 의 상태 만 업 데 이 트 했 고 교체 기 에 있 는 expected ModCount 가 동기 화 되 지 않 아 Iterator.next()방법 을 다시 호출 할 때 이상 을 던 졌 습 니 다.그런데 왜 Iterator.remove()를 사용 하면 문제 가 없 을까요?원본 코드 32 줄 을 통 해 Iterator 의 reove()에서 expected ModCount 의 값 을 동기 화 했 기 때문에 다음 에 next()를 호출 할 때 이상 이 없 는 지 확인 합 니 다.
이 메커니즘 을 사용 하 는 주요 목적 은 ArrayList 의 빠 른 실패 메커니즘(fail-fast)을 실현 하기 위해 서 이다.자바 집합 에서 비교적 큰 부분 집합 은 빠 른 실패 메커니즘 이 존재 한다.
빠 른 실패 메커니즘 이 발생 하 는 조건:여러 스 레 드 가 Collection 을 조작 할 때 한 스 레 드 가 Iterator 를 통 해 집합 을 옮 겨 다 닐 때 이 집합 내용 이 다른 스 레 드 에 의 해 바 뀌 면 Concurrent ModificationException 이상 을 던 집 니 다.
따라서 Iterator 를 사용 하여 집합 을 옮 겨 다 닐 때 오류 가 발생 하지 않도록 집합 을 옮 겨 다 니 는 과정 에서 집합 에 구조 적 인 수정 이 일어나 지 않도록 해 야 한다.
Foreach 를 사용 할 때 집합 구 조 를 수정 하면 이상 이 발생 합 니 다.
위 에서 말 했 듯 이 Iterable 인 터 페 이 스 를 실현 하 는 종 류 는 Foreach 를 통 해 옮 겨 다 닐 수 있다.그것 은 foreach 가 Iterable 인터페이스 에서 돌아 오 는 Iterator 대상 에 의존 해 야 하기 때문에 본질 적 으로 Foreach 는 교체 기 를 사용 하고 foreach 를 사용 할 때 집합 구 조 를 수정 하 는 것 이다.Iterator 를 사용 할 때 집합 구 조 를 수정 하 는 것 과 본질 적 으로 같다.그래서 똑 같이 이상 을 던 지고 빠 른 실패 체 제 를 집행 한다.
foreach 는 JDK 1.5 에 새로 추 가 된 순환 구조 로 foreach 의 등장 은 우리 가 집합 하 는 행 위 를 간소화 하기 위 한 것 이다.
for 순환 과 교체 기의 대비:
* 효율 적 으로 각각 장점 이 있다.
> Array List 는 무 작위 접근 이 빠 르 고 for 순환 에서 사용 하 는 get()방법 은 무 작위 접근 방법 을 사용 하기 때문에 Array List 에서 for 순환 이 빠르다.
> LinkedList 는 순서 접근 이 빠 르 고 Iterator 의 next()방법 은 순서 접근 방법 을 사용 하기 때문에 LinkedList 에서 Iterator 를 사용 하 는 것 이 빠르다.
> 주로 집합 한 데이터 구조 에 따라 다른 판단 을 해 야 한다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JAVA 객체 작성 및 제거 방법정적 공장 방법 정적 공장 방법의 장점 를 반환할 수 있습니다. 정적 공장 방법의 단점 류 공유되거나 보호된 구조기를 포함하지 않으면 이불류화할 수 없음 여러 개의 구조기 파라미터를 만났을 때 구축기를 고려해야 한다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.