1. default 关键字
java里,接口是不能有方法的实现的。1.8 通过 default 关键字可以实现
public interface NewChar {public void test1();public default void test2(){System.out.println("我是新特性1");}}
作用是什么?
定义一个默认方法,这个接口的实现类实现了这个接口之后,不用管这个方法的实现,可以直接调用。
2. lambda 表达式
意味着开始使用函数式编程
函数式编程:
- 是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量。
- 也就是说,输入确定,输出也就是确定的。
特点
- 允许把函数本身作为参数传入另一个函数,还允许返回一个函数
格式
- ->符号
- 左侧 参数列表
- 右侧 所需的功能,即lambda体
先来看一个例子
//常规的 集合排序 需要对接口方法重写public void test1(){List<String> list =Arrays.asList("aaa","fsa","ser","eere");//对接口方法重写Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o2.compareTo(o1);}});for (String string : list) {System.out.println(string);}}//不带参数类型的lambda写法public void testLamda2(){List<String> list =Arrays.asList("aaa","fsa","ser","eere");// ->符号Collections.sort(list, (a,b)->b.compareTo(a));for (String string : list) {System.out.println(string);}
3. 函数式接口
仅仅只包含一个抽象方法的接口,每一个该类型的 lambda 表达式都会匹配到这个抽象方法
// 这个注解定义函数式接口@FunctionalInterfacepublic interface MyLamda {//只允许定义一个抽象方法public void test1(String y);//这里如果继续加一个抽象方法便会报错// public void test1();//default方法可以任意定义default String test2(){return "123";}default String test3(){return "123";}//static方法也可以定义static void test4(){System.out.println("234");}}
看一下调用抽象方法
MyLamda m = y -> System.out.println("ss"+y);
4. 方法和构造函数引用
符号 :: ClassName::MethodName 没有()
- 符号前面 目标引用
- 符号后面 方法名称
先定义一个函数式接口@FunctionalInterfacepublic interface TestConverT<T, F> {F convert(T t);}测试public void test(){//调用Integer的valueOf方法TestConverT<String, Integer> t = Integer::valueOf;Integer i = t.convert("111");System.out.println(i);}
对于构造方法也可以这样调用
//实体类User和它的构造方法public class User {private String name;private String sex;public User(String name, String sex) {super();this.name = name;this.sex = sex;}}//User工厂public interface UserFactory {User get(String name, String sex);}//测试类 这里编译器会根据uf调用的参数来选择合适的构造函数UserFactory uf = User::new;User u = uf.get("ww", "man");
5. 局部变量限制
- Lambda可以没有限制的捕获实例变量和静态变量。
- 但是局部变量必须声明为 final
- 使用lambda的线程,可能会在分配该变量的线程将这个变量回收之后,去访问的。
- 因此,在访问局部变量时,实际上是访问他的副本,而不是原始变量。
- 如果被final修饰之后,那就没什么区别了(原始和副本)
final int num = 1;Converter<Integer, String> stringConverter =(from) -> String.valueOf(from + num);stringConverter.convert(2);
6. Date api更新
7. Stream
定义:
- 不是集合元素,不是数据结构,不保存数据
- 更新一个高级版的Iterator,用户只需要给出对其包含的元素执行什么操作,stream会在内部进行遍历,做出相应的数据转换。
- 可以并行化操作,遍历时,数据会被分成多个段,每一个段都在不同的线程中处理,然后将结果一起输出。
类型有两种:
- Intermediate
- 打开流,做出某种数据映射或过滤,然后返回一个新的流。
- 一个流后可以跟0个或者多个这种流
- Terminal
- 会真正的开始流的遍历,并生成一个结果 或副作用(side effect)
- 所以一个流只能有一个terminal操作,执行完,流就被用光了。
int sum = widgets.stream()
.filter(w -> w.getColor() == RED)
.mapToInt(w -> w.getWeight())
.sum();
- stream() 获取当前widgets的source
- filter mapTotInt 为Intermediate操作,进行数据筛选和转换
- sum为terminal操作,得到一个求和的结果
所以流的使用就是实现一个 filter-map-reduce过程,产生一个结果或者导致一个副作用(side effect)
构造流的方式
// 1. Individual values
Stream stream = Stream.of("a", "b", "c");
// 2. Arrays
String [] strArray = new String[] {"a", "b", "c"};
stream = Stream.of(strArray);
stream = Arrays.stream(strArray);
// 3. Collections
List<String> list = Arrays.asList(strArray);
stream = list.stream();
流的操作 参考
- Intermediate
- map (mapToInt, flatMap 等)(映射)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
- Terminal
- forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
- Short-circuiting
- anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
8. Annotation注解
Java 8允许我们把同一个类型的注解使用多次,只需要给该注解标注一下@Repeatable即可。
注解拓展,注解几乎可以使用在任何元素上:局部变量、接口类型、超类和接口实现类。
9. Optional
解决空指针的问题
提供了一些方法,来做判断
//不管param是不是null 都不会抛出异常
Optional<String> nullOptional = Optional.ofNullable(param);
10. 新的工具和引擎
Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
11. HashMap 和 ConcurrerentHashMap 优化
- 链表树化
- 头插法改成尾插法
- ConcurrerentHashMap 改为 Node 数组 + cas + synchronized
12. synchronized 优化,锁膨胀
13. JVM 优化
Java 8 中就把方法区的实现移到了本地内存中的元空间中,这样方法区就不受 JVM 的控制了,也就不会进行 GC,也因此提升了性能
