Lambda表达式:
public class Test01 {
public static void main(String[] args) {
//无参无返回值的Lambda表达式
MyInter mi = ()->System.out.println("test方法被执行了");//方法体
mi.test();//执行方法
//有参无返回值的Lambda表达式
MyInter2 mi2 = x->System.out.println(x);
mi2.test(3);
//有参有返回值的Lambda表达式
MyInter3 mi3 = (x)->x*x;//只有一条返回语句时,如果省略{},那么return也要省略
System.out.println(mi3.test(4));
MyInter3 mi33 = (x)->{//只有一个参数()可以省略,没有参数()不可以省略
int sum = x + x;//方法体有多行内容可以写在{}中,有一行时,可以写也可以不写.
return sum;
};
int test = mi33.test(3);
System.out.println(test);
//无参有返回值的Lambda表达式
MyInter4 mi4 = ()->3;
System.out.println(mi4.test());
}
}
interface MyInter{
//无参无返回值
public void test();
}
interface MyInter2{
//有参无返回值
public void test(int x);
}
interface MyInter3{
//有参有返回值
public int test(int x);
}
interface MyInter4{
//无参有返回值
public int test();
}
函数式接口:
Lambda表达式使用的前提:就是接口必须是一个函数式接口。
格式检测:
@FunctionInterface
如果不是函数式接口,则编译报错
作用:
想表达的是一个方法的内容,由于方法不存在任何类中,所以称为函数
接口其实想表达的就是一个函数的声明
将来使用这个接口的实现类对象,来表达一个函数的实现
Java中不支持将函数作为一个数据,也就不能将这个函数进行各种传递,也就不能作为对象的成员变量存在,只能在方法外加一层接口的声明,【将来可以传递方法所在的接口的实现类对象,来间接地传递函数的内容】
常用内置函数式接口:
Consumer<T>:消费型接口
void accept(T t)
Supplier<T>:供给型接口
T get()
Function<T,R>:函数型接口
R apply(T t)
Predicate<T>:断言型接口
Boolean test(T t)
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class Test03 {
public static void main(String[] args) {
//消费型接口
Consumer<Integer> c = x->System.out.println(x);
c.accept(4);
//供给型接口
Supplier<Integer> s = ()->6;
System.out.println(s.get());
//函数型接口
Function<String,Integer> f = x->{
return Integer.parseInt(x);
};
System.out.println(f.apply("3"));
//断言型接口
Predicate<Integer> p = x->x>0;
System.out.println(p.test(100));
}
}
方法的引用:
写一个函数式接口时,方法的实现,已经被其化的对象实现了,就不需要Lambda体中,再次调用这个实现,而可以直接使用已经定好的方法。
格式:
函数式接口 名称 = 对象名::方法名称
函数式接口 名称 = 类名::静态方法名
作用:
把已经实现的方法,作为一个数据,作为一个引用,赋值给函数式接口的引用。
可以把这个引用当做方法的返回值,也可以作为方法实际参进行传递。
public class Test02 {
public static void main(String[] args) {
//test01();
test02();
}
private static void test01() {
Printer p = (x)->System.out.println(x);//方法体!!!
p.print("wakaka");
Printer p2 = System.out::println;//方法的引用:1.前面已经实现了这个类的方法,2.简写,连参数都不用加
p2.print("渴望着你的消息");
}
private static void test02() {
PrinterNum pn = x->{//花括号写在参数小箭头的后面!!!注意别写错了
x+=1;
System.out.println(x*x);
};
pn.print(3);
TestDemo td = new TestDemo();
PrinterNum pn2 = td::print;//使用方法的引用的时候,参数都不用写,额外的都不用写
}
}
class TestDemo{
public void print(int x) {
x+=1;
System.out.println(x*x);
}
//即便类中有同名重载方法也无所谓,会自动匹配需要的那个方法
}
interface PrinterNum{
void print(int x);
}
interface Printer{
public abstract void print(String str);
}
StreamingAPI:
jdk1.8中,提供一个Stream类型,可对数据进行过滤。
好处:比不断自定循环,要简单的多。
import java.util.ArrayList;
public class Test04 {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<String>();
names.add("张无忌");
names.add("张三疯");
names.add("周芷若");
names.add("张飞");
names.add("赵云");
names.add("古力娜扎");
names.add("迪丽热巴");
ArrayList<String> list = new ArrayList<String>();
//test01(names);
test02(names);
}
private static void test02(ArrayList<String> names) {
names.stream().filter(x->x.startsWith("张")).filter(x->x.length()==3).forEach(System.out::println);
}
private static void test01(ArrayList<String> names) {
ArrayList<String> list1 = new ArrayList();
for(String name:names) {
if(name.startsWith("张")) {
list1.add(name);
}
}
ArrayList<String> list2 = new ArrayList<String>();
for(String name:list1) {
if(name.length()==3) {
list2.add(name);
}
}
System.out.println(list2);
}
}
Stream类型的获取:
Collection的获取:
调用 stream()方法即可,返回 Stream类型的对象
Map的获取:
不能直接获取Stream类型
keySet().stream();
entrySet().stream();
values().stream();
数组的获取:
Stream.of(数组)
Stream 中的常用方法:
用于对流中的数据,进行过滤,筛选等操作。
分类:
终结方法:调用完成之后,返回值不再是Stream类型的本身,无法继续使用Stream中的方法。
forEach() count()
延迟方法:调用完之后,返回值还是Stream类型,可以继续调用Stream中的各种方法。
filter()
Stream<T> | filter(Predicate<? super T> predicate) 返回由与此给定谓词匹配的此流的元素组成的流。 | ||
Stream<T> | limit(long maxSize) 返回由此流的元素组成的流,截短长度不能超过 maxSize 。 | ||
Stream<T> | skip(long n) 在丢弃流的第一个 n元素后,返回由该流的 n元素组成的流。 | ||
<R> Stream<R> | map(Function<? super T,? extends R> mapper) 返回由给定函数应用于此流的元素的结果组成的流。 | ||
void | forEach(Consumer<? super T> action) 对此流的每个元素执行操作。 | ||
long | count() 返回此流中的元素数。 |
练习:
有两个Arraylist集合,存储队伍中的多个成员姓名,使用Stream方式,对以下步骤进行操作:
第一个队伍只要名字为3个字的成员姓名
第一个队伍只要筛选之后的前三个人
第二个队伍只要姓张的
第二个队伍筛选之后不要前两个人
将两个队伍合并成一个队伍
合并之后的队伍中的所有人的Person(自定义类型)对象,存储到一个ArrayList集合中
队伍1:宫本武藏、宋公明、苏有朋、石头人、时传祥、李耳、庄子、洪七公
队伍2:帕瓦罗蒂、张三疯、赵薇薇、张自忠、孛儿只斤铁木真、张天爱、张翠花
Arrays工具类中的asList方法,由数组转换为列表
static <T> List<T> | asList(T... a) 返回由指定数组支持的固定大小的列表。 |
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/*
有两个List集合,存储队伍中的多个成员姓名,使用Stream方式,对以下步骤进行操作
第一个队伍只要名字为3个字的成员姓名
第一个队伍只要筛选之后的前三个人
第二个队伍只要姓张的
第二个队伍筛选之后不要前两个人
将两个队伍合并成一个队伍
合并之后的队伍中的所有人的Person(自定义类型)对象,存储到一个ArrayList集合中
队伍1:宫本武藏、宋公明、苏有朋、石头人、时传祥、李耳、庄子、洪七公
队伍2:帕瓦罗蒂、张三疯、赵薇薇、张自忠、孛儿只斤铁木真、张天爱、张翠花
*/
public class Test05 {
public static void main(String[] args) {
String str1 = "宫本武藏、宋公明、苏有朋、石头人、时传祥、李耳、庄子、洪七公";
String str2 = "帕瓦罗蒂、张三疯、赵薇薇、张自忠、孛儿只斤铁木真、张天爱、张翠花";
String[] ss1 = str1.split("、");
String[] ss2 = str2.split("、");
List<String> list1 = Arrays.asList(ss1);
List<String> list2 = Arrays.asList(ss2);
Stream<String> s1 = list1.stream().filter(x->x.length()==3).limit(3);
Stream<String> s2 = list2.stream().filter(x->x.startsWith("张")).skip(2);
Stream<String> ss = Stream.concat(s1, s2);//合并两个流
List<Person> personList = new ArrayList<Person>();
ss.forEach(x->{
Person p = new Person(x);
personList.add(p);
});
System.out.println(personList);
}
}