最近面试总会被问到JDK8中的一些新特性,所以闲下来抽时间看了一下8的源码,目前主要看的是数据结构部分,特此记录一下。

新增函数式接口,实现该接口的可以直接用lambda表达式。

default和static关键字修饰接口中的方法,可以在方法中写实现。下方是Collection接口中实现的一个方法。

    default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}

Collection接口新增了spliterator(),stream(),parallelStream(),removeIf()方法。

spliterator()方法返回一个Spliterator对象。看到英文应该可以想到是split+iterator的意思,顾名思义,就是用来做拆分遍历。

该对象有2个比较重要的属性值,index是起始值(包含),fence为结束值(不包含)

可以通过trySplit()方法将其拆分。下面通过一段代码举例

 List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
list.add(8);
list.add(9);
list.add(10);
Spliterator<Integer> sp = list.spliterator();
Spliterator<Integer> sp1 = sp.trySplit();
Spliterator<Integer> sp2 = sp.trySplit();
Spliterator<Integer> sp3 = sp.trySplit();

可以通过debug查看各个对象中index和fence的值。trySplit()之后会从中间拆分,返回前半段,而把后半段保留在原对象中。

该接口的tryAdvance(Consumer action)方法,从index开始对元素进行某种操作,当还有元素未操作时,返回true,否则返回false。通常遍历时使用forEachRemaining(Consumer action);

estimateSize()方法返回还剩多少元素未处理

stream()方法返回一个Stream对象,该对象与我们之前用到的I/O流不同,是JDK8新增的一个接口。可以认为是一个更高级的iterator。该接口与IntStream,DoubleStream,IntStream都继承于BaseStream接口。最大的好处应该就是可以过滤筛选元素,不需要像之前要遍历每个元素去做筛选。

该接口有多个方法,下面介绍下各个方法的作用。

Stream<T> filter(Predicate<? super T> predicate);
根据表达式将符合表达式的元素返回。
XXXStream mapToXXX(ToXXFunction mapper):将元素按照ToXXFunction的复写方法去转换。
<R> Stream<R> map(Function<? super T, ? extends R> mapper):将元素按照Function的方法去转换
Stream flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);将集合中不同的元素结合到一起生成一个新的Stream
distinct(); 去重,根据元素的equals()方法去重
sorted();排序,按照默认排序规则排序
sorted(Comparator );按照给与规则排序
peek(Consumer action);重新生成原有Stream的所有元素的Stream,并给每个元素添加一个Consumer的消费函数,每个元素执行该函数。一般用于debug时
limit(int maxSize);将Stream进行截断操作,获取前maxSize个元素。
skip(int n);返回第n个元素以后的元素,如果Stream的大小不超过n,则返回空Stream。
forEach(Consumer action);对所有元素执行action操作。
toArray();返回包含所有元素的数组
reduce(BinaryOperator<T> accumulator);根据表达式做相应的运算直到最后。
collect(Supplier<R> supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);将元素放入结果容器中。
min(comparator);根据给定的比较方式,返回最小的
max(comparator);同上返回最大的
count();返回元素个数
anyMatch(Predicate);判断是否有符合表达式的元素,如果为空,则返回false
allMatch(Predicate);判断是否全部符合表达式,如果为空,则返回true;
noneMatch(Predicate);判断是否全部不符合
findFirst();找到第一个元素,如果为空,则返回空
findAny();返回任意一个。

Stream的创建:

可以通过builder()创建Builder然后创建

Empty();返回一个空Stream

Of(T… t);返回含有传入参数的Stream

Iterate(final T seed, UnaryOperator);以seed为基础,根据后面的响应操作表达式来添加元素,无限长度

Generate(Supplier);根据给定的方法来生成元素,无限长度

无限长度一般配合limit();使用

Concat(Stream a,Stream b);将两个Stream合并为一个,如果两个是有序的,则合并后有序,如果任意一个是并行的,则合并后并行,关闭合并的Stream则原有两个也关闭

parallelStream()方法,顾名思义,就是获取平行的Stream

removeIf(Predicate filter)方法可以用于批量删除集合中的符合filter的元素。下面介绍一下Predicate接口。

Predicate接口我们先看一下源码中的注译:

Represents a predicate (boolean-valued function) of one argument.

这可以认为是一个判别条件,用途是用来判断所给的元素是否符合某种不表达式;

该接口有5个方法:

新建对象时需要重写该方法,在其中写相应的判断
boolean test(T t);
与操作,获取两个Predicate的与
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
非操作,获取两个Predicate的非
default Predicate<T> negate() {
return (t) -> !test(t);
}
或操作,获取两个Predicate的或
default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); }
静态方法,返回一个Predicate,用于判断是否与传入的对象相同
static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }

下面用一个例子来说明这几个方法:

    
List<Student> ls = new ArrayList<Student>();
Student s = new Student("zhangsan",25);
Student s2 = new Student("lisi",30);
Student s3 = new Student("wangwu",10);
ls.add(s);
ls.add(s2);
        ls.add(s3);
    //这里可以写lambda表达式
Predicate<Student> p1 = new Predicate<Student>() { @Override
public boolean test(Student t) {
// TODO Auto-generated method stub
if(t.age>25)
return true;
return false;
}
};
Predicate<Student> p2 = p1.negate();
Predicate<Student> p3 = Predicate.isEqual(s);
ls.removeIf(p1);
     System.out.println(ls.toString());

上述代码的输出结果为:[Student [name=zhangsan, age=25], Student [name=wangwu, age=10]]

p1的表达式为 age>25的元素,所以只有一个元素被删除。

上面代码不动 将p1换为p2输出结果为:[Student [name=lisi, age=30]]

将p2换为p3输出结果为:[Student [name=lisi, age=30], Student [name=wangwu, age=10]]

我们将p1替换为p1.and(p3)结果为:[Student [name=zhangsan, age=25], Student [name=lisi, age=30], Student [name=wangwu, age=10]]

p1替换为p1.or(p3)结果为[Student [name=wangwu, age=10]]

这里就对这几个方法的用途很明确了。

JDK8源码阅读之Collection及相关方法的更多相关文章

  1. JDK源码阅读之Collection

    源码版本:JDK 1.7. 集合 Collection,根据已知的内容可以知道有List.Set.Map(严格说,Map不属于Collection)等大类. 先查看 Collection, publi ...

  2. JDK源码阅读(三) Collection<T>接口,Iterable<T>接口

    package java.util; public interface Collection<E> extends Iterable<E> { //返回该集合中元素的数量 in ...

  3. 源码阅读之HashMap(JDK8)

    概述 HashMap根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的. HashMap最多只允许一条记录的键为null,允许多条记录 ...

  4. 源码阅读之LinkedList(JDK8)

    inkedList概述 LinkedList是List和Deque接口的双向链表的实现.实现了所有可选列表操作,并允许包括null值. LinkedList既然是通过双向链表去实现的,那么它可以被当作 ...

  5. 源码阅读之ArrayList(JDK8)

    ArrayList概述 ArrayList是一个的可变数组的实现,实现了所有可选列表操作,并允许包括 null 在内的所有元素.每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组 ...

  6. java8 ArrayList源码阅读

    转载自 java8 ArrayList源码阅读 本文基于jdk1.8 JavaCollection库中有三类:List,Queue,Set 其中List,有三个子实现类:ArrayList,Vecto ...

  7. JDK 1.8源码阅读 HashMap

    一,前言 HashMap实现了Map的接口,而Map的类型是成对出现的.每个元素由键与值两部分组成,通过键可以找对所对应的值.Map中的集合不能包含重复的键,值可以重复:每个键只能对应一个值. 存储数 ...

  8. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  9. EventBus源码解析 源码阅读记录

    EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...

随机推荐

  1. vue笔记未整理

    全局组件 局部组件 子组件传值到父组件 父子组件传值 watch跟计算属性差不多,都会有缓存,计算属性优先 计算属性get set 对象 数组 对象 数组 不复用 改变数组 直接修改数组,页面没变化 ...

  2. Oracle硬解析,软解析,软软解析介绍

    Oracle数据库中的CURSOR分为两种类型:Shared Cursor 和 Session Cursor 1,Shared Cursor Oracle里的第一种类型的Cursor就是Shared ...

  3. python icmp\dns\http监控网络各个节点状态,并记录日志

    配置文件如下:支持多节点: { "dns":[{"domainname":"www.baidu.com","dnsserver&q ...

  4. SequoiaDB 巨杉数据库

    传统单点数据库的容量瓶颈,仅仅是分布式数据库所解决的问题之一.更重要的是在未来微服务化应用开发以及云化平台的趋势下,应用不再以“烟囱式”的中间件加数据库模式进行构建,而是采用数千甚至上万的微服务程序构 ...

  5. Python之shutil模块(复制移动文件)

    用python实现将某代码文件复制/移动到指定路径下.场景例如:mv ./xxx/git/project1/test.sh ./xxx/tmp/tmp/1/test.sh (相对路径./xxx/tmp ...

  6. SVN和Git 介绍,区别,优缺点以及适用范围

    SVN是Subversion的简称,是一个开放源代码的版本控制系统,支持大多数常见的操作系统.作为一个开源的版本控制系统,Subversion管理着随时间改变的数据.这些数据放置在一个中央资料档案库( ...

  7. springboot+shiro 一个项目部署多个,session名冲突问题

    问题 前几天遇到一个比较奇怪的问题, 一个项目部署多个,端口不同.启动之后在同一浏览器中进行登录,后一个登录的会把前一个登录的挤掉,导致只能登录一个. 原因 是因为sessionid相同,然后修改了s ...

  8. windows 平台使用 VS2017 编译openssl源码

    windows 平台使用 VS2017 编译openssl源码 1)依赖安装 安装 perl 脚本解释器 下载 http://libevent.net/download 安装 nasm 汇编器 C:\ ...

  9. Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3) D. Barcelonian Distance 几何代数(简单)

    题意:给出一条直线 ax +by+c=0  给出两个整点 (x1,y1) (x2,y2) 只有在x,y坐标至少有一个整点的时 以及   给出的直线才有路径(也就是格子坐标图的线上) 问 两个整点所需要 ...

  10. Going from u to v or from v to u? POJ - 2762(强连通 有向最长路径)

    In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, an ...