天天看點

Java集合源碼探究之周遊方式,Set List Map

疊代器接口

類圖

Java集合源碼探究之周遊方式,Set List Map

疊代器是一個接口, 首先看一下java對疊代器接口的描述資訊,以及這個接口定義的基本規範

疊代器接口的描述, 基本規範

實作這個接口, 允許一個對象成為深度 for - each 的目标。并且能夠使用泛型。

  • iterator
    • 傳回一個疊代器
  • forEach(Consumer<? super T> action)
    • 對每一個元素示範提供的動作, 直到所有的元素全部通過或者有一個元素抛出異常, 除非實作類有其他的規定,疊代器将按照順序執行,操作引發的異常被中繼到調用方。
  • default
    • 在接口中可以使用default關鍵字來修飾一些預設實作的方法。
public interface Iterable<T> {
 
    Iterator<T> iterator();
 
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
 
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

           
測試
public class test implements Iterable<Integer> {

   @Override
   public Iterator<Integer> iterator() {
       return null;
   }

   @Override
   public void forEach(Consumer<? super Integer> action) {
       action.accept(3);
   }

   @Override
   public Spliterator<Integer> spliterator() {
       return null;
   }

   public static void main(String[] args) {
       test test = new test();
       test.forEach(System.out::println);
   }
}
           

對疊代器簡單探究

ArrayList

疊代器方式

Collection接口也是疊代器接口的子接口, 則其必須對疊代器接口中做出的規範進行實作,下面進行簡單的探究, 在java的集合架構中, 會存在一個簡單的三層模型, 分别是

  • 最上層的接口
    • 定義規範
  • 中間層的抽象類
    • 對一些特殊的規範做出統一(或者特殊)的實作
  • 最下層的具體實作類
    • 根據自己的特電重寫實作類中的實作, 和最上層接口中定義的規則。

對于這三層,将通過ArrayList進行探究, 先看下類圖

  • ArrayList 繼承 AbstractList
  • AbstractList 繼承 AbstractCollection
    • AbstractList 實作 List 接口
  • AbstractColleciont 實作 Collection
Collection 接口

我們先看下 Collection 接口中疊代器相關的。幾乎沒有對疊代器接口做出任何的改動, 最上層的接口用來定義規範!

Iterator<E> iterator();

    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }
           
AbstractColleciont 實作類

AbstractColleciont 這給抽象類也隻是對 Collection 中的一些普遍方法做出了一些實作,對于疊代器部分也是沒做出修改。

List接口

此接口中又定義了一個ListIterator 的方法, 用作List集合的疊代!

ListIterator<E> listIterator();   
	
	ListIterator<E> listIterator(int index);
           
AbstractList 實作類

在這個抽象類中終于看到了關于疊代器的部分!可以看到最上層的疊代器方法中傳回了一個疊代器對象!按照内部類的方式進行傳回, 來探究以下其中的方法實作!

  • cursor
    • 記錄着我們通過疊代器傳回了幾個元素
  • lastRet
    • 記錄這我們最後一個傳回元素的位置
  • expectedModCount
    • 我們期望被修改的次數, 用來判斷并發!
  • public boolean hasNext()
    • 和 cursor 以及 size() 方法一起來判斷是否還有下一個元素
  • public E next()
    • 傳回下一個元素
  • public void remove()
  • 删除最近周遊的元素
public Iterator<E> iterator() {
        return new Itr();
    }

    private class Itr implements Iterator<E> {
 
        int cursor = 0;
 
        int lastRet = -1;
 
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size();
        }

        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
           
arrayList 類

方法實作上基本和AbstractList 類似, 隻不過多了具體 forEachRemaining(Consumer<? super E> consumer) 的實作, 以及forEach的重寫(重寫的是疊代器接口中預設的實作)

  • forEach
    • 其中周遊集合中的每一個元素, 對其進行我們的action!
@Override
    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;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

    public Iterator<E> iterator() {
        return new Itr();
    }
 
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
           

List類

  • 疊代器周遊
  • for 循環周遊
  • forEach周遊
public static void main(String[] args) {
        Integer[] ints = {1, 2, 3, 4};
        ArrayList<Integer> integers = new ArrayList<Integer>(Arrays.asList(ints));
        Iterator<Integer> iterator = integers.iterator();
        iterator.next();
        iterator.remove();
        while (iterator.hasNext()) {
            System.out.println("while");
            System.out.println("->" + iterator.next());
        }

        integers.forEach(System.out::println);

        for (int i = 0; i < integers.size(); i++) {
            System.out.println(integers.get(i));
        }

    }
           

Set類

  • set.iterator();
  • set.toArray();
public static void main(String[] args) {
        HashSet<Integer> set = new HashSet<>();
        set.add(2);
        set.add(3);
        set.add(4);
        set.add(5);
        Iterator<Integer> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        for (Integer integer : set) { 	
            System.out.println(integer);
        }

        Object[] toArray = set.toArray();
        for (Object o : toArray) {
            System.out.println(o);
        }
    }
           

Map類

  • map.keySet();
  • map.values();
  • map.entrySet();
public static void main(String[] args) {

        HashMap<String, Object> map = new HashMap<>();
        map.put("1", "1");
        map.put("2", "2");

        Set<Map.Entry<String, Object>> entries = map.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            System.out.println(entry.getKey() + "- >" + entry.getValue());
        }

        Set<String> strings = map.keySet();
        for (String string : strings) {
            System.out.println(string);
        }
        
        Collection<Object> values = map.values();
        for (Object value : values) {
            System.out.println(value);
        }
    }