1. default 关键字

java里,接口是不能有方法的实现的。1.8 通过 default 关键字可以实现

  1. public interface NewChar {
  2. public void test1();
  3. public default void test2(){
  4. System.out.println("我是新特性1");
  5. }
  6. }

作用是什么?
定义一个默认方法,这个接口的实现类实现了这个接口之后,不用管这个方法的实现,可以直接调用。

2. lambda 表达式

意味着开始使用函数式编程
函数式编程:

  • 是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量。
  • 也就是说,输入确定,输出也就是确定的。

特点

  • 允许把函数本身作为参数传入另一个函数,还允许返回一个函数

格式

  • ->符号
  • 左侧 参数列表
  • 右侧 所需的功能,即lambda体

先来看一个例子

  1. //常规的 集合排序 需要对接口方法重写
  2. public void test1(){
  3. List<String> list =Arrays.asList("aaa","fsa","ser","eere");
  4. //对接口方法重写
  5. Collections.sort(list, new Comparator<String>() {
  6. @Override
  7. public int compare(String o1, String o2) {
  8. return o2.compareTo(o1);
  9. }
  10. });
  11. for (String string : list) {
  12. System.out.println(string);
  13. }
  14. }
  15. //不带参数类型的lambda写法
  16. public void testLamda2(){
  17. List<String> list =Arrays.asList("aaa","fsa","ser","eere");
  18. // ->符号
  19. Collections.sort(list, (a,b)->b.compareTo(a)
  20. );
  21. for (String string : list) {
  22. System.out.println(string);
  23. }

3. 函数式接口

仅仅只包含一个抽象方法的接口,每一个该类型的 lambda 表达式都会匹配到这个抽象方法

  1. // 这个注解定义函数式接口
  2. @FunctionalInterface
  3. public interface MyLamda {
  4. //只允许定义一个抽象方法
  5. public void test1(String y);
  6. //这里如果继续加一个抽象方法便会报错
  7. // public void test1();
  8. //default方法可以任意定义
  9. default String test2(){
  10. return "123";
  11. }
  12. default String test3(){
  13. return "123";
  14. }
  15. //static方法也可以定义
  16. static void test4(){
  17. System.out.println("234");
  18. }
  19. }

看一下调用抽象方法

  1. MyLamda m = y -> System.out.println("ss"+y);

4. 方法和构造函数引用

符号 :: ClassName::MethodName 没有()

  • 符号前面 目标引用
  • 符号后面 方法名称
  1. 先定义一个函数式接口
  2. @FunctionalInterface
  3. public interface TestConverT<T, F> {
  4. F convert(T t);
  5. }
  6. 测试
  7. public void test(){
  8. //调用Integer的valueOf方法
  9. TestConverT<String, Integer> t = Integer::valueOf;
  10. Integer i = t.convert("111");
  11. System.out.println(i);
  12. }

对于构造方法也可以这样调用

  1. //实体类User和它的构造方法
  2. public class User {
  3. private String name;
  4. private String sex;
  5. public User(String name, String sex) {
  6. super();
  7. this.name = name;
  8. this.sex = sex;
  9. }
  10. }
  11. //User工厂
  12. public interface UserFactory {
  13. User get(String name, String sex);
  14. }
  15. //测试类 这里编译器会根据uf调用的参数来选择合适的构造函数
  16. UserFactory uf = User::new;
  17. User u = uf.get("ww", "man");

5. 局部变量限制

  • Lambda可以没有限制的捕获实例变量和静态变量。
  • 但是局部变量必须声明为 final
    • 使用lambda的线程,可能会在分配该变量的线程将这个变量回收之后,去访问的。
    • 因此,在访问局部变量时,实际上是访问他的副本,而不是原始变量。
    • 如果被final修饰之后,那就没什么区别了(原始和副本)
  1. final int num = 1;
  2. Converter<Integer, String> stringConverter =
  3. (from) -> String.valueOf(from + num);
  4. 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,也因此提升了性能