上一节咱们缕清了Collection家族的关系,接下来咱们就来看看这个家族的创始者及其师傅。java
1. 师傅Iterablec++
Iterable是一个接口类,先看看接口里面的方法:数组
其中第二个和第三个方法,都是java8新增的,看源码会发现,java8后,能够在接口里面定义默认(关键字default)的方法(必须实现,能够空实现),并且实现类中还能够重写default方法,这样一来有点相似抽象类,只不过接口类用来授艺,抽象类用来遗传。最终给咱们代码的迭代带来很大便利。ide
Iterable里面最主要的固然迭代器Iterator,Iterator自己是接口,这么说来接口师傅(水平有限)传授的都是大道的终极要义,功夫仍是得弟子苦练。后来师傅能力提高(java8来了),能够给弟子大道的精华(default方法),让弟子能够绝不费力直接领悟,甚至弟子还能够加以创新(重写),可是要注意多接口实现形成的默认方法冲突问题(冲突很容易解决,就很少说)。关于Iterator在子类的实现能够查看ArrayList源码,很简单,只是你们用得多的是next()方法,不知有没有注意到previous()方法。值得一提的是在Iterator接口里面新增了默认方法:forEachRemaining方法,容许传入一个行为,其实就相似于Iterable的forEach方法。函数
一看forEach方法,就知道这是遍历集合的,可是通常咱们遍历集合可能有两种缘由:一筛选出特定的元素(须要返回值);二处理元素(无需返回值)。由此一看这个方法它没有返回值,顿时就肯定这是处理元素。咱们看看forEach的参数:Consumer。ui
@FunctionalInterface public interface Consumer<T> { void accept(T t); default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
Consumer:FunctionalInterface说明该接口属于函数式接口。它表示一个接受单个输入参数而且没有返回值的操做。不像其余函数式接口,Consumer接口指望执行带有反作用的操做,即Consumer的操做可能会更改输入参数的内部状态。如今java类的方法里面能够直接传递函数,而不只限于值了。这在c++里面叫函数指针。this
从accept方法可知Consumer能够表明任意函数,但该函数的参数个数限制为一个且无返回值。指针
public class Main { public static void main(String[] args) { //eg.1 String hello = "hello world!"; Consumer<String> c = (str) -> System.out.println(str.toUpperCase()); c.accept(hello); //eg.2 List<Student> list = Arrays.asList(new Student("Ben", 80), new Student("John", 90)); Consumer<Student> consumer = new Consumer<Student>() { @Override public void accept(Student s) { s.score *= 0.9; } }; //list.forEach(consumer); list.forEach(consumer.andThen(consumer)); //每一个元素先执行调用者行为,而后在执行参数行为 list.forEach(new Consumer<Student>() { //打印 @Override public void accept(Student s) { System.out.println(s.name + ": " + s.score); } }); } static class Student { String name; int score; public Student(String name, int score) { this.name = name; this.score = score; } } }
至于第三个方法spliterator()返回的是一个分片迭代器,它能够将集合分红多个片断,每一个片断能够并行处理,在多核CPU下十分高效。在后面章节我会单独起一章讲解。code
2. 徒弟Collection接口
Collection接口除了一些基本的添加、移除、清除,转数组等操做,值得注意的仍是新增的默认方法。
default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; } default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } default Stream<E> parallelStream() { return StreamSupport.stream(spliterator(), true); }
在这里我简单介绍一下Predicate接口,它也是函数式接口,其实就相似于Consumer,只不过Consumer是处理数据,没有返回值,而Predicate是进行一些逻辑处理,返回一个boolean值。其余两个默认方法是将集合数据流化,便于作一些过滤,也看到了stream()方法里面也进行了分片迭代处理。
关于java8新特性Stream的讲解,也排在后面的章节。
好了,两个接口的讲解就到此结束了。