Java集合源码解读(第一篇–Colletion解读)

集合概述

Java的集合主要是由两个接口接口一个是Colletions接口、一个是Map接口

mark

mark

Colletion接口的实现方法

mark

我们可以发现Collection的源码中继承了Iterable,有iterator()这个方法…

public interface Collection<E> extends Iterable<E> 
public interface Iterable<T> {
    // 有iterator()这个方法…
    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
    // JDK8 新的接口,spliterator()方法返回一个Spliterator对象,split+iterator的意思,顾名思义,就是用来做拆分遍历。
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}
public interface Iterator<E> {
    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

关于迭代器接口在不同的接口中的实现,关于ArrayList中实现

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() {
            .......
        }

        public void remove() {
            ........
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
           ........
        }
    }

可见集合的遍历实现为内部类实现了Iterator的接口,然后每个集合不同的实现都能实现相同的方法。

遍历集合的几种方式


  1. forEach遍历

    Iterator接口新增加了forEach默认的方法,该方法所需要的类型是一个函数式接口,当程序调用forEach遍历集合的时候,程序会依次将集合元素传给Consumer的accept(T t)方法,可以说调用forEach实际上就是使用forIn循环来使用。

        Collection books = new HashSet();
        books.add("轻量级Java EE企业应用实战");
        books.add("疯狂Java讲义");
        books.add("疯狂Android讲义");
        // 调用forEach()方法遍历集合
        books.forEach(obj -> System.out.println("迭代集合元素:" + obj));
    
  2. 使用Iterator遍历集合元素
        Iterator it = books.iterator();
        while(it.hasNext())
        {
            // it.next()方法返回的数据类型是Object类型,因此需要强制类型转换
            String book = (String)it.next();
            System.out.println(book);
               if (book.equals("疯狂Java讲义"))
            {
                // 从集合中删除上一次next方法返回的元素
                it.remove();
            }
            // 对book变量赋值,不会改变集合元素本身,Iterator并不把集合元素本身传递给迭代变量,而是把值传递给变量。
            book = "测试字符串";   //①
        }
        System.out.println(books);
    
  3. 使用Lambda表达式遍历集合
        // 获取books集合对应的迭代器
        Iterator it = books.iterator();
        // 使用Lambda表达式(目标类型是Comsumer)来遍历集合元素
        it.forEachRemaining(obj -> System.out.println("迭代集合元素:" + obj))
    
  4. forEach循环遍历集合
        for (Object obj : books)
        {
            // 此处的book变量也不是集合元素本身
            String book = (String)obj;
            System.out.println(book);
            if (book.equals("疯狂Android讲义"))
            {
                // 下面代码会引发ConcurrentModificationException异常
                   // forEach中的循环变量不是集合本身,系统只是依次把集合元素的值赋值给迭代变量
                books.remove(book);     //①
            }
        }
        System.out.println(books);
    
  5. Colletion集合中新增加的 **removeIf(Predicate filter)** 操作集合
        ........
        // 使用Lambda表达式(目标类型是Predicate)过滤集合
        books.removeIf(ele -> ((String)ele).length() < 10);
        System.out.println(books);
    

    更加高级的功能

        // 统计书名包含“疯狂”子串的图书数量
        System.out.println(calAll(books, ele -> ((String) ele).contains("疯狂")));
    
        // 统计书名包含“Java”子串的图书数量
        System.out.println(calAll(books, ele -> ((String) ele).contains("Java")));
    
        // 统计书名字符串长度大于10的图书数量
        System.out.println(calAll(books, ele -> ((String) ele).length() > 10));
    
        public static int calAll(Collection books, Predicate p) {
            int total = 0;
               for (Object obj : books) {
                   // 使用Predicate的test()方法判断该对象是否满足Predicate指定的条件
                   if (p.test(obj)) {
                       total++;
                   }
               }
            return total;
        }
    

常见的具体的集合库

mark

markmark