目录
Lambda表达式
函数式接口
1、Supplier
2、Consumer
3、Predicate
4、Function
Stream流
Stream流的获取方式:
常用方法:
Lambda表达式,也可以称为闭包,是Java8的重要特性。使用Lambda表达式可以是代码变得更加简洁紧凑。
Lambda的格式:三个部分:
1)一些参数 2)一个箭头 3)一些代码
标准格式:
(参数)->{一些代码};
省略规则
小括号中的参数数据类型可以直接省略
如果小括号中只有一个参数,小括号可以直接省略
如果大括号中只有一句代码,不管有没有返回值,可以同时省略return关键字,大括号以及分号。
// 1. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
// 2. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 5. 不需要参数,返回值为
() -> 5
使用lambda表达式的前提:
1)使用lambda必须具有接口,并且要求有且仅有一个抽象方法 无论是JDK内置的Runnable,Comparator接口还是自定义接口,只有当接口中的抽象方法存在且唯一是时才可以使用Lambda
2)使用lambda表达式必须具有上下文推断 即方法的参数或局部变量类型必须为lambda对应的接口类型,才能使用Lambda作为接口的实例
如果一个接口他的抽象方法只有一个,这个接口就叫做函数式接口(和其他非抽象方法无关)。如果不清楚这个是否为函数式接口,可以使用注解@FunctionalInterface检查当前接口是否为函数式接口
接下来介绍四种常见的函数式接口。
1)java.util.function.Supplier
:接口仅包含一个无参的方法,T get():用来获取一个泛型参数执行类型的对象数据,由于此接口是一个函数式接口,即对应的Lambda表达式需要提供一个符合泛型类型的对象的数据。 此接口是一个生产型接口,指定接口的泛型是一个什么类型,那么接口中的get方法就会产生什么类型的数据
public class DemoSupplier {
public static void main(String[] args) {
//调用getString方法,方法参数supplier是一个函数式接口,所以可以传递lambda表达式
String s=getString(()-> {
//生产一个字符串,并返回
return "James";
});
String s1 = getString(()->"Jerry");
System.out.println(s);
System.out.println(s1);
}
//定义一个方法,方法的参数 传递supplier接口,泛型执行string,get方法就会返回一个string
public static String getString(Suppliersupplier){
return supplier.get();
}
}
java.util.function.Consumer
:此接口正好与Supplier接口相反,Supplier是一个生产数据的接口,而Consumer是一个消费数据的接口,其数据类型也由泛型决定。 Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据
public class DemoConsumer {
public static void main(String[] args) {
//调用method犯法,传递字符串姓名,方法的另一个参数是Consumer接口,
//是一个函数式接口,所以可以传递Lambda表达是
method("James", (String name)->{
//对传递的字符串进行消费
//消费方式:直接输出字符串
System.out.println (name);
//翻转字符串
String reName=new StringBuffer(name).reverse().toString();
System.out.println( reName);
});
}
public static void method(String name, Consumercon){
con.accept(name);
}
}
java.util.function.Predicate
接口:用于对某种类型进行判断,从而得到一个boolean值,Predicate接口中包含一个抽象方法:boolean test(T t).
public class DemoPredicate {
public static void main(String[] args) {
//定义一个字符串
String s = "abcdefg";
//调用checkstring方法对字符串进行校验,参数传递字符串和lambda表达式
boolean b = checkString(s, (str) ->
//对参数进行传递的字符串进行判断,判断字符串的长度是否大于5,并把判断的结果返回
str.length() > 7);
System.out.println(b);
}
public static boolean checkString(String s, Predicate predicate) {
return predicate.test(s);
}
}
java.util.function.Function
:该接口是用来根据一个类型的数据得到拎一个类型的数据,前者称之为前置条件,后者称之为后置条件。 Function接口中最主要的抽象方法是R apply(T t),根据类型T大的参数获取类型R的接口
public class DemoFunction {
public static void main(String[] args) {
//定义一个字符串类型整数
String s="124";
//调用change方法,传递字符串类型的整数和lambda表达式
change(s,(str)->Integer.parseInt(s));
}
public static void change(String s,Function function){
int in=function.apply(s);
System.out.println(in);
}
}
Stream流用于解决已有集合类库的既有的弊端。Stream流得益于Lambda的功能,因为有了Lambda表达式才有了Stream流
Stream流的获取方式:
1)Collection单列集合:集合.stream()
2)数组: Stream.of(数组)
3)Map双列集合:
集合.keySet().stream() ---》j键
集合.values().stream() ---》值
package com.itheima_06;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public class Test01 {
public static void main(String[] args) {
//把集合和数组转化成Stream流
//单列集合
ArrayList list = new ArrayList<>();
list.add(123);
list.add(456);
list.add(789);
//把单列集合转化成Stream流
Stream stream1 = list.stream();
//双列集合(扩展)
//双列集合不能转成Stream,需要把键和值单独转化
Map map = new HashMap<>();
map.put(1,"柳岩");
map.put(2,"张三");
//把双列集合转成Stream流
//键
Stream stream2 = map.keySet().stream();
//值
Stream stream3 = map.values().stream();
//数组
Integer[] arr = {11,22,33,44};
Stream stream4 = Stream.of(arr);
}
}
常用方法:
1、终结方法:意味着调用之后就不能再调用流的其他方法了。
- count():返回流中元素的个数
- forEach():遍历元素---》forEach传递的参数就是Consumer
接口
//forEach使用
public class Demo01 {
public static void main(String[] args) {
//创建list集合
Listlist = new ArrayList<>();
Collections.addAll(list,"张三丰","王思聪","张飞","刘晓敏","张靓颖");
//使用stream流打印数据
Stream stream = list.stream();
stream.forEach(s-> System.out.println(s));
}
}
//count使用
public class Demo03 {
public static void main(String[] args) {
//创建list集合
List list = new ArrayList<>();
Collections.addAll(list,"张三丰","王思聪","张飞","刘晓敏","张靓颖");
//使用stream流打印数据
Stream stream = list.stream();
//筛选所有“张"姓学员
long l = stream.filter(s -> s.startsWith("张")).count();
System.out.println("张姓学员为"+l+"个");
}
}
非终结方法:指stream流调用之后可以继续调用流的其他方法
- filter():过滤方法 ----》filter传递的参数是Predicate接口
- limit():取用前几个
- skip():跳过前几个
- map():映射方法,可以把元素从一种类型转成另一种类型 ----》map传递的接口是Function接口
- static concat():把两个stream流合并成一个Stream
public class Demo02 {
public static void main(String[] args) {
//创建list集合
List list = new ArrayList<>();
Collections.addAll(list, "张三丰", "王思聪", "张飞", "刘晓敏", "张靓颖");
//使用stream流打印数据
Stream stream = list.stream();
stream.filter(s -> s.startsWith("张")).forEach(s ->System.out.println(s));
}
}
public class Demo04 {
public static void main(String[] args) {
//创建list集合
List list = new ArrayList<>();
Collections.addAll(list,"张三丰","王思聪","张飞","刘晓敏","张靓颖","王敏");
//使用stream流打印数据
Stream stream = list.stream();
//筛选集合中所有张姓学员
stream.filter(s->s.startsWith("张")).limit(2).forEach(s-> System.out.println(s));
System.out.println("=============================");
//重新获取stream流
Streamstream1= list.stream();
//筛选所有王姓人员
stream1.filter(s->s.startsWith("王")).skip(1).forEach(s-> System.out.println(s));
}
}
public class Demo05 {
public static void main(String[] args) {
//创建list集合
List list = new ArrayList<>();
Collections.addAll(list,"张三丰","王思聪","张飞","刘晓敏","张靓颖","王敏");
//使用stream流打印数据
Stream stream = list.stream();
//使用map()方法将每个元素封装为一个Person对象(创建一个Person类,name属性)
List collect = stream.map(s -> new Person(s)).collect(Collectors.toList());
System.out.println(collect);
}
}
public class Demo05 {
public static void main(String[] args) {
//创建list集合
List list = new ArrayList<>();
Collections.addAll(list, "张三丰", "王思聪", "张飞", "刘晓敏", "张靓颖", "王敏");
//使用stream流打印数据
Stream stream = list.stream();
//筛选集合中所有张姓学员
stream = stream.filter(s -> s.startsWith("张"));
System.out.println("=============================");
//重新获取stream流
Stream stream1 = list.stream();
//筛选所有王姓人员
stream1 = stream1.filter(s -> s.startsWith("王"));
//合并流
Stream stream2 = Stream.concat(stream, stream1);
stream2.forEach(s -> System.out.println(s));
}
}