Java8特性
- 1.Lambda表达式
- 语法
- 2.函数式接口
- 3.方法、构造器的引用
- 4.Stream API
- 5.BufferedReader lines 转换成Stream
1.0 Lambda表达式
1.1 语法
- Lambda表达式引入新的操作符"->";
- 左侧:表达式需要的参数
- 右侧:Lambda体需要执行的功能
1.1.1 无参数,无返回值
Runnable r2 = ()->System.out.println("lambda:无参数无返回值")
1.1.2 有一个参数无返回值
Consumer<String> consumer = (t)->System.out.println(t);
consumer.accept("有没有为谁拼过命");
1.1.2 只有一个参数时小括号可以去除
Consumer<String> consumer1 = t->System.out.println(t);
consumer1.accept("有没有为谁拼过命");
1.1.3 Lambda 需要两个参数,并且有返回值
Comparator<Integer> comp =(x,y)->{
return Integer.compare(x, y);
};
int result = comp.compare(100, 99);
System.out.println(result);
1.1.4 Lambda 体只有一条语句时,return 与大括号可以省略
Comparator<Integer> comp =(x,y)-> Integer.compare(x, y);
int result = comp.compare(100, 99);
System.out.println(result);
1.1.5 数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
Comparator<Integer> comp2 =(Integer x,Integer y)-> Integer.compare(x, y);
int result2 = comp2.compare(90, 99);
System.out.println(result2);
2.0 函数式接口
2.1 概念
- 只包含一个抽象方法的接口,称为函数式接口
- 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)
- 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口
2.2 四大核心函数式接口
2.2.1 消费型接口:Consumer < T >
- 参数类型 T
- 返回类型 void
- 对类型为T的对象操作,应用方法 void accept(T t)
Consumer<String> consumer = (t)->System.out.println(t);
consumer.accept("Consumer");
2.2.2 供给型接口:Supplier < T>
- 参数:无
- 返回类型 T
- 返回包含为T的对象,T get();
Supplier<String> supplier = ()-> "获取我的值";
String supplierRet = supplier.get();
System.out.println(supplierRet);
2.2.3 函数型接口:Function<T,R>
- 参数:T
- 返回对象:R
- 对类型为T的对象操作,返回类型为R的对象
Function<String, Integer> fun = (x)-> x.length();
System.out.println(fun.apply("function()->"));
2.2.4 断言型接口:Predicate< T>
- 参数:T
- 返回: boolean
- 确定型为T的对象是否满足某约束条件,方法:boolean test(T t)
Predicate<String> predicate = (Str)->Str.length()>=3 ;
List<String> list = Arrays.asList("6","01","1314","520");
List<String> filterList = new ArrayList<>();
for(String str:list){
if(predicate.test(str)){
filterList.add(str);
}
}
System.out.println(filterList);
3.0方法的引用与构造器引用
3.1 方法引用:
- 当要传递给Lambda体的操作,已有实现的方法,可以使用方法的引用。
- 操作符:利用 "::"将方法名和类或对象名分隔开。
3.1.1 语法:
- 1.对象::实例方法
- 2.类::静态方法
- 3.类::实例方法
3.2 构造器引用
- 概念:与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!
- 格式:ClassName::new
Function<String, Apple> apples = (s)-> new Apple(s);
Apple apple = apples.apply("小苹果");
System.out.println(apple);
Function<String,Apple> apples1 = Apple :: new ;
System.out.println(apples1.apply("大苹果"));
~~~
### 3.3 数组引用
- 1.格式:type [] :: new
```java
Function<Integer, String []> arrFun = (s)-> new String [s] ;
System.out.println("非数组引用结果:"+arrFun.apply(10).length);
Function<Integer, String []> arrNewFun = String[] :: new ;
System.out.println("数组引用结果:"+arrNewFun.apply(10).length);
4.0 Stream API
4.1 概念
- 1.Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作
- 2.使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作
- 3.简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式
4.2 Stream 的特点
- Stream 自己不会存储元素
- Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream
- Stream 操作是延迟执行的,这意味着他们会等到需要结果的时候才执行
4.3 Stream 的操作三个步骤
- 创建 Stream(一个数据源如:集合、数组,获取一个流)
- 中间操作(一个中间操作链,对数据源的数据进行处理)
- 终止操作(一个终止操作,执行中间操作链,并产生结果)
4.3.1 创建Stream的方法
- 1.Java8 中的 Collection 接口被扩展,提供了两个获取流的方法
List<String> streamList = new ArrayList<>();
Stream<String> stream = streamList.stream();
- 2.ava8 中的 Arrays 的静态方法 stream() 可以获取数组流
int [] array = new int [5];
IntStream stream2 = Arrays.stream(array);
- 3.可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数
Stream<String> stream3 = Stream.of("0","1","2");
- 4.可以使用静态方法 Stream.iterate() 和Stream.generate(), 创建无限流。
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x++);
stream4.limit(6).forEach(System.out :: println);
Stream.generate(() -> Math.random()).limit(6)
.forEach(System.out :: println);
4.4 Stream的中间操作
4.4.1 筛选和切片
- filter():接收Lambda,从Stream中排除某些元素
- distinct():通过流生成的元素hashcode及equals去重
- limit(1):截断流,不超过给定数量
- skip(0):跳过前n个元素的流
List<Apple> apples = Arrays.asList(
new Apple("green", "绿苹果"),
new Apple("red", "红苹果"),
new Apple("red", "红苹果"),
new Apple("green", "绿苹果1"));
apples.stream().filter((a)->a.getColor().equals("green")).limit(1).distinct().skip(0).forEach(System.out::println);
4.4.2 映射
- map(Function f):接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
- mapToInt(ToIntFunction f):接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream
- flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
List<String> list = Arrays.asList("a","bb","ccc","dddd");
list.stream().map((str) -> str.length())
.forEach(System.out :: print);
4.4.3 排序
- sorted():产生一个新流,其中按自然顺序排序
- sorted(Comparator comp):产生一个新流,其中按比较器顺序排序
4.5 终止流
4.5.1 定义:
- 终端操作会从流的流水线生成结果。其结果可以是任何不是流的值例如:List,void
4.5.1 检查与匹配
- allMatch(Predicate p):检查是否匹配所有元素
- anyMatch(Predicate p):检查是否至少匹配一个元素
- noneMatch(Predicate p):检查是否没有匹配所有元素
- findFirst(): 返回第一个元素
- findAny() 返回当前流中的任意元素
- count() 返回流中元素总数
- max(Comparator c) 返回流中最大值
- min(Comparator c) 返回流中最小值
- forEach(Consumer c):内部迭代
4.5.2 归约
- reduce(T iden, BinaryOperator b):可以将流中元素反复结合起来,得到一个值,返回 T
- reduce(BinaryOperator b):可以将流中元素反复结合起来,得到一个值,返回 Optional
4.5.3 收集
- collect(Collector c):将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
- toList
- toSet
- toCollection
- counting:计算元素个数
- summingInt:对流中元素的整数属性求和
- averagingInt:计算流中元素Integer属性的平均值
5.0 BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("e://1.txt")));
String line = "";
List<String> comList = new ArrayList<String>();
while((line = br.readLine())!=null){
comList.add(line);
}
br.close();
System.out.println(comList);
Stream<String> lines = br.lines();
List<String> str = lines.collect(Collectors.toList());
System.out.println(str);