ArrayList 분석

오늘 은 자바 의 목록ArrayList을 돌 이 켜 보면 일련의 대상 을 배열 로 저장 하고 지원 하 는 것 을 나타 낸다.
우 리 는 오늘 그것 의 기초 속성,첨가 방법,그리고 lambda 와 관련 된 부분 을 연구 합 니 다.
속성
기본 용량
List의 초기 화 공간 을 표시 합 니 다.
    private static final int DEFAULT_CAPACITY = 10;

빈 목록
매개 변수 에 값 을 부여 할 수 있 도록 빈 배열 목록 두 개 를 제공 합 니 다.
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

메모리 그룹
배열 범 형 에 저 장 된 데 이 터 는 배열 로 이 루어 집 니 다.
    transient Object[] elementData; // non-private to simplify nested class access

목록 크기ArrayList목록 에 포 함 된 요소 개 수 를 표시 합 니 다.기본 값 은 0 입 니 다.
    private int size;

용량 을 늘리다
사실size우리 가 가장 먼저ArrayList의 확장 방법 을 언급 할 때 가 많다 면,우리 쪽 에 서 는 확장 방법 에 관 한 일련의 방법 체인 을 연구 해 보 자.ArrayList이름 이ArrayList인 익명 방법 이 있 습 니 다.말 그대로 확장 입 니 다.(핵심)을 살 펴 보 겠 습 니 다.
    private void grow(int minCapacity) {
        //          
        int oldCapacity = elementData.length;
        //                       
        int newCapacity = oldCapacity + (oldCapacity >> 1);

        //                     (         )
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;

        //MAX_ARRAY_SIZE       Integer - 8 (2147483639)
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            /*
                       minCapacity     2147483639  
                             
            */
            newCapacity = hugeCapacity(minCapacity);

        //           ,       ,       ,           
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

그 중에서 우 리 는grow방법 을 호출 했다.
    private static int hugeCapacity(int minCapacity) {

        //          
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();

        //   MAX_VALUE    MAX_VALUE-8
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

그래서 우 리 는 목록 의 길이 가 특별히 크게 변 하지 않 은 상황 에서 새로운 배열 의 길 이 는 일반적으로 원래 의 길이 의 1.5 배 로 변 한 다 는 것 을 알 게 되 었 다.
그래서 우리 가hugeCapacity방법 을 호출 할 때 다음 과 같은 일이 발생 할 것 이다.
    public boolean add(E e) {
        //          ,            
        ensureCapacityInternal(size + 1);
        //  size          
        elementData[size++] = e;�
        return true;
    }

    private void ensureCapacityInternal(int minCapacity) {
        //         ,       
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        //          
        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        //         ,    add          grow
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

그래서 우 리 는 사실 핵심 코드 가add방법 인지,다른 것 은 모두 특수 한 상황 을 처리 하 는 것 임 을 발견 할 것 이다.
찾다grow에서 몇 가지 유사 한 방법 이 있 는데 그들 은 모두 하나의 특성 을 가지 고 있다.즉,목록 에서 특정한 요 소 를 찾 아 특정한 조작 을 수행 할 수 있다 는 것 이다.예 를 들 어:
    public boolean contains(Object o);
    public int indexOf(Object o);
    public int lastIndexOf(Object o);
    public boolean remove(Object o);

이런 방법 들 은 모두 매우 유사 하기 때문에 우 리 는 지금ArrayList방법 을 연구 해 보 자.
    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;
    }

작은 매듭
분명히 우 리 는 결론 을 얻 을 수 있다.
  • 우 리 는 대상 을 찾 을 때 for 로 배열 의 모든 요 소 를 순환 합 니 다
  • 대상 을 찾 을 때 우 리 는indexOf방법
  • 을 사용한다.
    함수 방법equals에서 몇 가지 방법 이 있 는데 함수 인 터 페 이 스 를 매개 변수 로 하 는데 각각 다음 과 같은 방법 이다.
        public void forEach(Consumer super E> action);
        public boolean removeIf(Predicate super E> filter);
        public void replaceAll(UnaryOperator operator);
        public void sort(Comparator super E> c);
    

    다음 에 우 리 는 상기 몇 가지 방법 에 대해 예 를 들 어 사용 하거나 코드 분석 을 할 것 이다.
    forEach ArrayList방법 은 하나의 consumer 에 전달 한 다음 에 우리 가 들 어 온 lambda 에 따라 목록 의 모든 요소 에 대해 소비 행 위 를 하도록 요구한다.
    소스 코드
        public void forEach(Consumer super E> action) {
            //       
            Objects.requireNonNull(action);
            //        ,          
            final int expectedModCount = modCount;
            @SuppressWarnings("unchecked")
            final E[] elementData = (E[]) this.elementData;
            final int size = this.size;
    
            //          ,           
            //modCount                 ,      �           
            for (int i=0; modCount == expectedModCount && i < size; i++) {
                action.accept(elementData[i]);
            }
            //                    ,      
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
        }
    

    밤.
        @Test
        public void base05(){
            List arrayList = Arrays.asList(1,2,3,4,5);
            arrayList.forEach(i -> {
                System.out.println(i);
            });
        }
    

    removeIf forEach방법 은"predicate"를 입력 하고 반환 값 을 true 로 제거 하 는 방법 을 요구 합 니 다.stream 의 filter 와 유사 합 니 다.
    밤.
        @Test
        public void base06(){
            List arrayList = Arrays.asList(1,2,3,4,5);
            ArrayList newList = new ArrayList(arrayList);
            newList.removeIf(i -> {
                return i % 2 == 0;
            });
            newList.forEach(i -> {
                System.out.println(i);
            });
        }
    

    replaceAll removeIf방법 은 Unary Operator 함 수 를 받 아들 여 같은 유형의 데 이 터 를 되 돌려 원래 의 데 이 터 를 교체 합 니 다.
    소스 코드
        public void replaceAll(UnaryOperator operator) {
            //    
            Objects.requireNonNull(operator);
            //        ,          
            final int expectedModCount = modCount;
            final int size = this.size;
    
            //          ,         
            //modCount                 ,      �           
            for (int i=0; modCount == expectedModCount && i < size; i++) {
                elementData[i] = operator.apply((E) elementData[i]);
            }
            //                    ,      
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }
    

    밤.
        @Test
        public void base07(){
            List arrayList = Arrays.asList(1,2,3,4,5);
            ArrayList newList = new ArrayList(arrayList);
            newList.replaceAll(i -> {
                return 10 - i;
            });
            newList.forEach(i -> {
                System.out.println(i);
            });
        }
    

    sort replaceAll방법 은 comparator 인터페이스 대상 의 함 수 를 입력 하여 두 수의 크기 를 비교 하 는 함 수 를 나타 낸다.
    소스 코드
        public void sort(Comparator super E> c) {
            final int expectedModCount = modCount;
            Arrays.sort((E[]) elementData, 0, size, c);
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }
    

    밤.
        @Test
        public void base08(){
            List arrayList = Arrays.asList(934,2,13,43,5);
            ArrayList newList = new ArrayList(arrayList);
            newList.sort((a,b) -> {
                if(a > b){ return 1;}
                else {return -1;}
            });
            newList.forEach(i -> {
                System.out.println(i);
            });
        
    
    sort에 관 한 공 부 는 여기까지 입 니 다.그 후에 우 리 는ArrayList에 관 한 내용 을 계속 공부 할 것 입 니 다.
    제 블 로그 에 오신 것 을 환영 합 니 다:오신 김 에 앉으세요.

    좋은 웹페이지 즐겨찾기