Java8新特性总结

lambda表达式

基础用法就是一个接口里面一个函数,然后就可以开心使用了。

Java8内置了一些核心的函数式接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface Consumer<T> {
void accept(T t);
}

public interface Supplier<T> {
T get();
}

public interface Function<T, R> {
R apply(T t);
}

public interface Predicate<T> {
boolean test(T t);
}

所以用起来就会比较规范:

1
2
3
4
5
6
7
8
9
10
11
public class Main {
public static void main(String[] args) {
shopping(10, (money) -> {
System.out.println("花了" + money + "元");
});
}

public static void shopping(double money, Consumer<Double> consumer) {
consumer.accept(money);
}
}

方法引用

另外一种lambda的表现形式,有三种使用方法:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法

比如我们经常要打印某些信息,但是显然System.out这个类里面的println方法已经替我们实现了,所以我们其实可以直接用System.out::println来代替它(当然在这个例子中可能并没那么简便…),而且调用的方法需要和接口中的方法调用和返回值都相同。

Stream API

首先它是一个流,所以是用来进行数据操作的。其次它和普通IO流的区别就是,它面向的是集合和数组等;它对这些数据源进行一系列的操作,比如切片等,然后产生新的流,原来的数据源不发生任何变化。

  • 创建源
    • Collection接口里提供了stream()和parallelStream(),所以集合都可以直接使用。
    • 通过Arrays.stream()静态方法来创建数组的静态流。
    • 通过Stream.of()方法来创建。
    • 创建无限流
      • 迭代的方式:Stream.iterate(seed,一个表达式)
      • 生成的方式:Stream.generate(Supplier t)
  • 中间操作:内容较多,单独作为一章。中间操作并不会执行任何操作,直到终止操作才会执行——惰性求值。
  • 终止操作

中间操作

filter
1
Stream<T> filter(Predicate<? super T> predicate);

传入了一个断言接口,所以我们可以直接在其中用lambda来使用。

例子:

1
2
3
4
List<String> strings = Arrays.asList("aa", "bb", "cc");
strings.stream()
.filter((x) -> x.startsWith("a"))
.forEach(System.out::println);
limit
1
Stream<T> limit(long maxSize);

使用起来非常方便。它会产生短路,即只要知道对应的数量,后续的迭代操作就不需要执行了。

skip
1
Stream<T> skip(long n);

emmm 和limit形成互补的操作,跳过前n个元素。

distinct
1
Stream<T> distinct();

通过hashCode和equals方法来进行判断的。