왜 아 리 는 ArrayList 의 subList 방법 을 신 중 히 사용 해 야 합 니까?
집합 은 자바 개발 의 일상적인 개발 에서 자주 사용 되 는 것 이다.
집합 류 에 대해 알 리 바 바 자바 개발 매 뉴 얼 에는 또 다른 규정 이 있다.
본문 은 왜 이런 건의 가 있 는 지 분석 해 보 자.그 배후 의 원 리 는 무엇 입 니까?
subList
subList 는 List 인터페이스 에서 정 의 된 방법 입 니 다.이 방법 은 집합 중의 한 단락 을 되 돌려 주 는 데 사 용 됩 니 다.집합 중의 일부 요 소 를 캡 처 하 는 것 으로 이해 할 수 있 습 니 다.그의 반환 값 도 List 입 니 다.
다음 코드 와 같이:
public static void main(String[] args) {
List<String> names = new ArrayList<String>() {{
add("Hollis");
add("hollischuang");
add("H");
}};
List subList = names.subList(0, 1);
System.out.println(subList);
}
이상 코드 출력 결 과 는:[Hollis]
코드 를 바 꾸 면 subList 의 반환 값 을 Array List 로 강하 게 바 꿔 보 세 요.
public static void main(String[] args) {
List<String> names = new ArrayList<String>() {{
add("Hollis");
add("hollischuang");
add("H");
}};
ArrayList subList = names.subList(0, 1);
System.out.println(subList);
}
이상 코드 는 이상 을 던 집 니 다:
java.lang.ClassCastException: java.util.ArrayList$SubList cannot be cast to java.util.ArrayList
Array List 로 강하 게 전환 하 는 것 뿐만 아니 라 링크 드 List,Vector 등 List 로 강하 게 전환 하 는 실현 류 도 모두 틀 릴 수 있다.그렇다면 왜 이런 오류 가 발생 했 을 까?우 리 는 이어서 깊이 분석 해 보 자.
기본 원리
우선,subList 방법 이 우리 에 게 되 돌아 오 는 List 가 무엇 인지 살 펴 보 겠 습 니 다.이 점 은 JDK 소스 코드 에 이렇게 설명 되 어 있 습 니 다.
Returns a view of the portion of this list between the specifiedfromIndex, inclusive, and toIndex, exclusive.
즉,subList 반환 은 하나의 보기 입 니 다.그렇다면 보기 란 무엇 입 니까?
subList 의 소스 코드 를 보 겠 습 니 다.
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
이 방법 은 SubList 를 되 돌려 줍 니 다.이 종 류 는 Array List 의 내부 클래스 입 니 다.SubList 클래스 에 서 는 set,get,size,add,remove 등 방법 을 단독으로 정의 합 니 다.
subList 방법 을 호출 할 때 SubList 의 구조 함 수 를 호출 하여 SubList 를 만 듭 니 다.그러면 이 구조 함수 가 어떤 일 을 했 는 지 보 겠 습 니 다.
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
이 구조 함수 에서 원래 의 List 와 이 List 의 일부 속성 을 자신의 속성 에 직접 할당 하 는 것 을 볼 수 있 습 니 다.즉,SubList 는 List 를 다시 만 들 지 않 고 기 존의 List(부모 클래스 의 보 기 를 되 돌려 주 었 습 니 다)를 직접 인용 한 것 입 니 다.그 가 사용 할 요소 의 범 위 를 지 정 했 을 뿐 입 니 다(from Index(포함)에서 toIndex(포함 되 지 않 음).
그래서 왜 subList 방법 으로 얻 은 집합 을 Array List 로 바 꿀 수 없 습 니까?SubList 는 ArrayList 의 내부 클래스 일 뿐 이들 사이 에 통합 관계 가 없 기 때문에 직접 강제 유형 전환 을 할 수 없다.
보기 에 무슨 문제 가 있 습 니까?
앞에서 원본 코드 를 보면 subList()방법 은 Array List 를 다시 만 들 지 않 고 Array List 의 내부 클래스 인 SubList 를 되 돌려 주 었 다 는 것 을 알 수 있 습 니 다.
이 SubList 는 ArrayList 의 보기 입 니 다.
그렇다면 이 보 기 는 또 어떤 문 제 를 가 져 올 까?우 리 는 간단하게 몇 단락 의 코드 를 써 서 좀 볼 필요 가 있다.
비구 조 적 변화 SubList
public static void main(String[] args) {
List<String> sourceList = new ArrayList<String>() {{
add("H");
add("O");
add("L");
add("L");
add("I");
add("S");
}};
List subList = sourceList.subList(2, 5);
System.out.println("sourceList : " + sourceList);
System.out.println("sourceList.subList(2, 5) List :");
System.out.println("subList : " + subList);
subList.set(1, "666");
System.out.println("subList.set(3,666) List :");
System.out.println("subList : " + subList);
System.out.println("sourceList : " + sourceList);
}
결과 얻 기:
sourceList : [H, O, L, L, I, S]
sourceList.subList(2, 5) List :
subList : [L, L, I]
subList.set(3,666) List :
subList : [L, 666, I]
sourceList : [H, O, L, 666, I, S]
set 방법 을 통 해 subList 의 특정한 요 소 를 바 꾸 려 고 시 도 했 을 때 우 리 는 원래 의 List 에서 대응 하 는 요소 의 값 도 바 뀌 었 다 는 것 을 알 게 되 었 다.마찬가지 로 우리 가 같은 방법 으로 sourceList 의 특정한 요 소 를 수정 하면 subList 에 대응 하 는 값 도 달라 집 니 다.독자 가 스스로 시도 해 볼 수 있다.
구조 적 변화 서브 리스트
public static void main(String[] args) {
List<String> sourceList = new ArrayList<String>() {{
add("H");
add("O");
add("L");
add("L");
add("I");
add("S");
}};
List subList = sourceList.subList(2, 5);
System.out.println("sourceList : " + sourceList);
System.out.println("sourceList.subList(2, 5) List :");
System.out.println("subList : " + subList);
subList.add("666");
System.out.println("subList.add(666) List :");
System.out.println("subList : " + subList);
System.out.println("sourceList : " + sourceList);
}
결과 얻 기:
sourceList : [H, O, L, L, I, S]
sourceList.subList(2, 5) List :
subList : [L, L, I]
subList.add(666) List :
subList : [L, L, I, 666]
sourceList : [H, O, L, L, I, 666, S]
우 리 는 subList 의 구 조 를 바 꾸 려 고 시도 했다.즉,추가 요 소 를 시도 한 결과 sourceList 의 구조 도 똑 같이 바 뀌 었 다.구조 적 변화 원 List
public static void main(String[] args) {
List<String> sourceList = new ArrayList<String>() {{
add("H");
add("O");
add("L");
add("L");
add("I");
add("S");
}};
List subList = sourceList.subList(2, 5);
System.out.println("sourceList : " + sourceList);
System.out.println("sourceList.subList(2, 5) List :");
System.out.println("subList : " + subList);
sourceList.add("666");
System.out.println("sourceList.add(666) List :");
System.out.println("sourceList : " + sourceList);
System.out.println("subList : " + subList);
}
결과 얻 기:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1239)
at java.util.ArrayList$SubList.listIterator(ArrayList.java:1099)
at java.util.AbstractList.listIterator(AbstractList.java:299)
at java.util.ArrayList$SubList.iterator(ArrayList.java:1095)
at java.util.AbstractCollection.toString(AbstractCollection.java:454)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.hollis.SubListTest.main(SubListTest.java:28)
우 리 는 sourceList 의 구 조 를 바 꾸 려 고 시도 했다.즉,추가 요 소 를 시도 한 결과 Concurrent ModificationException 을 던 진 것 으로 나 타 났 다.작은 매듭
간단하게 요약 하면 List 의 subList 방법 은 새로운 List 를 만 들 지 않 고 원래 List 의 보 기 를 사 용 했 습 니 다.이 보 기 는 내부 클래스 SubList 로 표 시 됩 니 다.
따라서 우 리 는 subList 방법 이 되 돌아 오 는 List 를 Array List 등 유형 으로 강제 전환 할 수 없다.왜냐하면 그들 사이 에는 상속 관계 가 없 기 때문이다.
또한,보기 와 원 List 의 수정 은 몇 가지 더 주의해 야 합 니 다.특히 그들 간 의 상호 영향:
1.부모(sourceList)자(subList)List 에 대한 비 구조 적 수정(non-structural changes)은 서로 에 게 영향 을 미친다.
2.하위 List 에 대해 구조 적 인 수정 을 하면 작업 도 부모 List 에 반 영 됩 니 다.
3.부모 List 를 구조 적 으로 수정 하면 이상 Concurrent ModificationException 을 던 집 니 다.
그래서 알 리 바 바 자바 개발 매 뉴 얼 에는 또 다른 규정 이 있다.
새 List 만 드 는 방법
subList 를 수정 해 야 한다 면,원래 list 를 건 드 리 고 싶 지 않 습 니 다.subList 의 복사 본 을 만 들 수 있 습 니 다:
subList = Lists.newArrayList(subList);
list.stream().skip(strart).limit(end).collect(Collectors.toList());
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Java의 ArrayList 작동 원리 상세 정보수조로 실현하다.공간을 절약하지만 수조는 용량 제한이 있다.제한을 초과하면 50% 용량이 증가하며 System을 사용합니다.arraycopy () 를 새 그룹으로 복사합니다.따라서 수조 크기의 예비 평가를 하는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.