天天看点

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);
        }
    }