- 如果方法有返回值且方法体中只有return这一行代码,return可省略,如果不写,必须随同花括号一起省略
public class Test01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
TestInterface testInterface = (a,b) -> a+b;
System.out.println(testInterface.add(2,3)); //5
TestInterface2 testInterface2 = a -> System.out.println(a + 1);
testInterface2.m1(3); //4
}
}
@FunctionalInterface
interface TestInterface{
int add(int a,int b);
}
@FunctionalInterface
interface TestInterface2{
void m1(int a);
}
JDK提供的四大函数式接口
Suplier<T> 无参有返回值
Consumer 一个参数无返回值
Predicate<T> 一个参数返回boolean类型
Function<T,R> 一个参数有返回值
public class Test01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//无参有返回值
Supplier<Integer> supplier = () -> 1;
System.out.println(supplier.get()); //1
//有参返回布尔
Predicate<Integer> predicate = (a) -> a > 5 ? true:false;
System.out.println(predicate.test(6)); //true
//一个参数无返回值
Consumer<Integer> consumer = a -> System.out.println(a);
consumer.accept(1); //1
//有参数有返回值
Function<Integer,Integer> function = a -> a + 1;
System.out.println(function.apply(1)); //2
}
}
lamdba表达式引用方法
我们可以使用lamdba表达式的接口指向一个已经被实现过的方法(就是有方法体的方法)
语法:
方法归属者::方法名
-
- 静态方法的归属者为类名
- 实例方法的归属者为对象
public class Test01 {
public static void main(String[] args){
Function<Integer,Integer> fun = Test01::doubleNum;
System.out.println(fun.apply(3)); //6
Function<Integer,Integer> fun1 = new Test01()::doubleNum2;
System.out.println(fun1.apply(4)); //8
}
public static int doubleNum(int num){
return num*2;
}
public int doubleNum2(int num){
return num*2;
}
}
当函数式接口方法的第一个参数,是实现方法的调用者,并且第二个参数(如果有的话),是需要调用方的参数时(或无参数时)
- 类型::方法名
public class Test01 {
public static void main(String[] args){
Function<String,Integer> fun = str -> str.length();
System.out.println(fun.apply("string")); //6
}
}
public class Test01 {
public static void main(String[] args) {
//第二个参数为第一个参数调用方法的参数
MyInterface myInterface = BigInteger::add;
System.out.println(myInterface.m1(new BigInteger("1"), new BigInteger("2")));
}
}
@FunctionalInterface
interface MyInterface {
BigInteger m1(BigInteger a,BigInteger b);
}
public class Test01 {
public static void main(String[] args) {
MyInterface myInterface = Student::setName;
myInterface.m1(new Student(),"张三");
/*我是学生,名字是张三*/
}
}
class Student {
private String name;
public Student() {
}
public void setName(String name) {
this.name = name;
System.out.println("我是学生,名字是" + name);
}
}
@FunctionalInterface
interface MyInterface {
void m1(Student stu,String name);
}
lamdba引用构造方法
public class Test01 {
public static void main(String[] args) {
//无参
StudentBlankCon studentBlankCon = () -> new Student();
StudentBlankCon studentBlankCon2 = Student::new;
System.out.println(studentBlankCon.getStu()); //Student{name='Zhangsan', age=1, score=11}
System.out.println(studentBlankCon2.getStu()); //Student{name='Zhangsan', age=1, score=11}
//全参,lamdba表达式会根据参数类型的不同调用相关的构造方法
StudentAllParamCon studentAllParamCon = (name,age,score) -> new Student(name,age,score);
System.out.println(studentAllParamCon.getStu("Lisi", 12, 90));//Student{name='Lisi', age=12, score=90}
StudentAllParamCon studentAllParamCon1 = Student::new;
System.out.println(studentAllParamCon.getStu("Lisi", 12, 90));//Student{name='Lisi', age=12, score=90}
}
}
class Student {
private String name = "Zhangsan";
private int age = 1;
private int score = 11;
public Student() {
}
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
@FunctionalInterface
interface StudentBlankCon {
Student getStu();
}
@FunctionalInterface
interface StudentAllParamCon {
Student getStu(String name, int age, int score);
}
lamdba表达式对线程创建的支持
public class Test01 {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName());
}
},"t1");
t1.start();
}
}
lamdba表达式操作集合
遍历集合
public class Test01 {
public static void main(String[] args) {
//元素遍历
ArrayList<Integer> arrayList = new ArrayList<Integer>();
//使用Collections工具类批量添加元素
Collections.addAll(arrayList,1,2,3,4,5,6,7,8,9);
//lamdba表达式遍历集合 forEach(Consumer 自带函数式接口,有参无返回值)
arrayList.forEach( i -> System.out.println(i));
//ladba对System.out.println的支持
//如果遍历出来的元素以print/println形式打印
arrayList.forEach(System.out::println);
}
}
lamdba表达式对print/println的支持
//如果遍历出来的元素以print/println形式打印
arrayList.forEach(System.out::println);
删除集合中的元素
public class Test01 {
public static void main(String[] args) {
//元素遍历
ArrayList<Integer> arrayList = new ArrayList<Integer>();
//使用Collections工具类批量添加元素
Collections.addAll(arrayList,10,20,30,40,50,60,70,80,90);
//removeIf(Predicate 内置函数式接口,一个参数有返回值);
/*arrayList.removeIf(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer.equals(10);
}
});*/
//lamdba简化
arrayList.removeIf((i) -> i.equals(10));
System.out.println(arrayList);
}
}
集合中元素的排序
public class Test01 {
public static void main(String[] args) {
//元素遍历
ArrayList<Item> arrayList = new ArrayList<Item>();
//使用Collections工具类批量添加元素
Collections.addAll(arrayList,new Item(1,"牙刷",1.2),new Item(3,"凳子",0.2),new Item(2,"椅子",0.01));
/*arrayList.sort(new Comparator<Item>() {
@Override
public int compare(Item o1, Item o2) {
return o1.getId()- o2.getId();
}
});*/
//lamdba表达式
arrayList.sort( (o1,o2) -> o1.getId() - o2.getId() );
System.out.println(arrayList);
//[item{id = 1, name = 牙刷, price = 1.2}, item{id = 2, name = 椅子, price = 0.01}, item{id = 3, name = 凳子, price = 0.2}]
}
}
函数式编程(流式编程)
- 为了支持函数式编程的接口,为函数式接口
-
- 函数式接口,要求只能有一个自己的抽象方法(被注解@FunctionalInterface修饰)
- 在编写业务的过程中,以纯函数的书写操作流程作为主要的实现方式
- 面向对象以操作对象为思想核心,而函数式编程是以操作函数实现流程为思想核心,他们的关注点是不同的
- 函数式编程最标准的实现方式
-
- 从以前的数据参数化,转变为行为参数化
-
-
- 以前传入的是数据,现在传入的是行为
-
//lamdba表达式
arrayList.sort( (o1,o2) -> o1.getId() - o2.getId() );
-
- 如何行为参数化:lamdba表达式
- Java语言中的函数式编程完全是由lamdba表达式支持的,而lamdba表达式只能操作函数式接口(只有一个抽象方法的接口),有很强的局限性
Stream流处理集合
- Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。
-
- 用于简化集合/数组操作的API
- 怎么简化:函数式编程
- 需求
-
- 将一组学生的姓名保存到集合中
- 从集合中筛选出以z开头的学生的姓名,保存到一个集合中
- 从集合中筛选出姓名超过10个字符的学生姓名,保存到一个新的集合中。
public class Test01 {
public static void main(String[] args) {
//集合创建
List<String> list = new ArrayList<String>();
Collections.addAll(list,"zhangsan","zhangguorong","zhangguolao","zhangshaohan","lisi","wangwu");
//筛选z开头的加入新集合
List<String> l1 = new ArrayList<String>();
/*for (String s : list) {
if (s.startsWith("z")) {
l1.add(s);
}
}*/
list.forEach((s) -> {
if (s.startsWith("z")) {
l1.add(s);
}
});
System.out.println(l1);
//[zhangsan, zhangguorong, zhangguolao, zhangshaohan]
//从l1中再次筛选超过10个字符的(用stream流)
//新建集合
List<String> l2 = new ArrayList<String>();
l1.forEach((s) -> {
if (s.length() > 10) {
l2.add(s);
}
});
System.out.println(l2);
//[zhangguorong, zhangguolao, zhangshaohan]
//使用stream流,经过stream流操作之后,原来的集合list,没有受到影响
List<String> newList = list.stream().filter(s -> s.startsWith("z")).filter(s -> s.length() > 10).collect(Collectors.toList());
System.out.println(newList); //[zhangguorong, zhangguolao, zhangshaohan]
}
}
- 使用Stream流的思想
-
- 集合 --> stream流 --> 过滤 -->过滤 --> ... -->forEach打印/转换为新的集合。
- 操作stream流的三类方法
-
- 获取stream流的方法
-
-
- 对于当前案例: list.stream()就获取了stream流
-
-
- 中间方法(处理集合)
-
-
- 好比流水线上的操作,一个步骤完成后及进行下一个步骤,对于当前案例,filter方法就是中间方法用来过滤元素的,中间方法可以有无限多个。
-
-
- 终结方法
-
-
- 流水线上最后一个操作
- 对于当前案例,就是用collect(Collectors.toList());将Stream转为List集合。
- 终结方法,只能有一个
-
集合和数组获取stream流的方式
- 集合
-
- Collection集合获取stream流的方式(List Set) 单列集合
- 调用stream()方法
Stream<String> stream = new ArrayList<String>().stream();
-
- Map集合获取stream流的方式 双列集合
- 键和值分别处理为stream流
- 键值对处理为stream流
Map<String,Object> map = new HashMap<String,Object>();
//将键和值分别处理为stream流
map.keySet().stream();
map.values().stream();
//将键值对处理为stream流
Stream<Map.Entry<String, Object>> stream = map.entrySet().stream();
- 数组获取stream流的方式
-
- 通过Arrays工具类调用Arrays.stream()方法
- 通过Stream.of()方法
String[] arr = {"aaa", "bbb", "ccc"};
//方式一,通过Arrays工具类调用Arrays.stream方法
Stream<String> stream = Arrays.stream(arr);
//方式二,使用Stream.of()方法
Stream<String> stream1 = Stream.of(arr);
//重载方法可直接将传入元素,自动生成数组stream
Stream<String> stream2 = Stream.of("aaa", "bbb", "ccc");
stream流的中间方法
- limit(long n)从前面提取n个元素
- skip(long n)排除前面n个元素
- map()对元素进行加工
- distinct()去重
- Stream.concat() 将N组流进行组合,得到新的流
-
- 不同泛型的流也可合并,合并后的泛型为他们共同父类或接口
public class Test01 {
public static void main(String[] args) {
//集合创建
List<String> list = new ArrayList<String>();
Collections.addAll(list,"zhangsan","zhangguorong","zhangguolao","zhangshaohan","lisi","wangwu");
System.out.println("提取后");
//提取前两个元素
list.stream().limit(2).forEach(System.out::println);
System.out.println("排除后");
//排除前两个元素
list.stream().skip(2).forEach(System.out::println);
//每个元素前加 姓名:
System.out.println("加工后");
list.stream().map(s -> "姓名:" + s).forEach(System.out::println);
//集合的组合
//生成新的流
Stream<String> stream1 = Stream.of("aaa", "bbb", "ccc");
Stream<Integer> stream2 = Stream.of(11,22,33);
//Serializable允许序列化接口,String和Integer类型都实现了Serializable接口
Stream<? extends Serializable> result = Stream.concat(stream1, stream2);
System.out.println("拼接后");
result.forEach(System.out::println);
Stream<String> stream = Stream.of("111", "111", "222", "222", "333", "333");
System.out.println("去重后");
stream.distinct().forEach(System.out::println);
}
}
stream流的终结方法
- forEach 遍历元素
- count 返回元素的数量,结果为long类型
- collect 返回新的集合
-
- 传入参数
-
-
- Collectors.toList() 返回List
- Collectors.toSet() 返回Set
-
- reduce 返回规约的结果
-
- 规约:将N多个数据,进行处理,最终得到一个数据
-
-
- stream规约操作:将stream流中的元素聚合 缩减为单个结果
-
public class Test01 {
public static void main(String[] args) {
//集合创建
List<String> list = new ArrayList<String>();
Collections.addAll(list,"zhangsan","zhangguorong","zhangguolao","zhangshaohan","lisi","wangwu");
//forEach()遍历
list.stream().filter(s -> s.length() >= 10).forEach(System.out::println);
//count()返回long类型的长度
long count = list.stream().filter(s -> s.length() >= 10).count();
System.out.println("元素数量为" + count);//元素数量为3
System.out.println("--------------------------------");//元素数量为3
//coolect()返回新的集合
list.stream().filter(s -> s.length() >= 10).collect(Collectors.toList());
//reduce()返回规约的集合
/*Optional<String> reduce = list.stream().filter(s -> s.startsWith("z")).reduce(new BinaryOperator<String>() {
@Override
public String apply(String s, String s2) {
//s为上一次运算的结果,s2为新加入的元素
return s + s2;
}
});*/
// reduce配合lamdba
Optional<String> opt = list.stream().reduce((s, s2) -> s + s2);
// 返回值是一个Optional对象,使用get()直接取得值
System.out.println(opt.get());//zhangsanzhangguorongzhangguolaozhangshaohanlisiwangwu
}
}
标签:jdk1.8,String,stream,lamdba,System,println,public,表达式,out
From: https://blog.csdn.net/weixin_44212870/article/details/136727323