函数式接口
常用函数式接口:Supplier Consumer Predicate Function
Supplier(生产者)
1、T get( ) - 得到一个对象
public class Demo {
// 为了使用Lambda表达式, 所以将Supplier作为方法参数使用
public static String getInstance(Supplier<String> sup) {
// 调用Supplier 的get方法
return sup.get();
}
public static void main(String[] args) {
// 调用getInstance方法, 需要传递一个Supplier接口实现类
// 又因为Supplier接口是函数式接口, 所以可以使用Lambda表达式
String str = getInstance(() -> {
// 这是生产字符串的过程
return "hello";});
System.out.println(str);
}
}
Consumer(消费者)
1、void accept(T t) - 使用这个对象
public class Demo {
/*
为了使用Lambda表达式, 需要将Consumer接口作为方法参数
因为Consumer接口的accept方法需要一个对象来消费, 所以再多传入一个String参数
*/
public static void toUpper(String str, Consumer<String> consumer) {
consumer.accept(str);
}
public static void main(String[] args) {
toUpper("hello", s -> {
// 在这里写消费/使用这个s对象的代码
// 消费方式: 将 s 进行反转
String str = new StringBuilder(s).reverse().toString();
System.out.println(str);
});
}
}
2、默认方法:andThen(Consumer) - 将两个消费方式组合在一块
public class Demo {
/**
* 因为要使用andThen方法, 所以需要两个Consumer对象
* 并且accept方法需要消费一个对象, 所以还需要一个String对象
*/
public static void methodAndThen(String str, Consumer<String> con1, Consumer<String> con2) {
/*con1.accept(str);
con2.accept(str);*/
con1.andThen(con2).accept(str);
}
public static void main(String[] args) {
methodAndThen("JavaGood",
// 第一次消费, 将字符串全部变大写, 并且打印
s -> {
System.out.println(s.toUpperCase());
},
// 第2次消费, 将字符串全部变小写, 并且打印
s -> {
System.out.println(s.toLowerCase());
});
}
}
Predicate
1、boolean test(T t) - 对对象做判断
public class Demo {
public static void method01(String str, Predicate<String> pre) {
boolean b = pre.test(str);
System.out.println(b);
}
public static void main(String[] args) {
method01("www", (s) -> {
return s.length() == 2;
});
}
}
2、默认方法:or(||) - and(&&) - negate(!)
public class DemoAnd {
public static void strPredicate(String str, Predicate<String> pre1, Predicate<String> pre2) {
/*boolean b1 = pre1.test(str);
boolean b2 = pre2.test(str);
System.out.println(b1 && b2);*/
boolean b = pre1.and(pre2).test(str);
System.out.println(b);
}
public static void main(String[] args) {
strPredicate("Hello Tony!",
s -> s.length() > 10,
s -> s.startsWith("H"));
}
}
public class DemoOr {
public static void strPredicate(String str, Predicate<String> pre1, Predicate<String> pre2) {
// boolean b = pre1.test(str) || pre2.test(str);
boolean b1 = pre1.or(pre2).test(str);
System.out.println(b1);
}
public static void main(String[] args) {
strPredicate("Hello Tony!",
s -> s.split(" ").length > 10,
s -> s.startsWith("H"));
}
}
public class DemoNegate {
public static void m1(String str, Predicate<String> pre) {
/*boolean b = pre.test(str);
System.out.println(!b);*/
boolean b1 = pre.negate().test(str);
System.out.println(b1);
}
public static void main(String[] args) {
m1("hello Tony !",
s -> s.split(" ")[1].length() > 3);
}
}
例:
public class DemoTest {
public static boolean filterName(String str, Predicate<String> p1, Predicate<String> p2) {
boolean b = p1.and(p2).test(str);
return b;
}
public static void main(String[] args) {
String[] array = {"abcd,女", "ww,女", "bcde,男", "cdef,女"};
ArrayList<String> list = new ArrayList<>();
for (String str : array) {
boolean b = filterName(str,
// 1.必须为女生;
s -> s.split(",")[1].equals("女"),
// 2.姓名为4个字。
s -> s.split(",")[0].length() == 4
);
if (b) {
list.add(str);
}
}
System.out.println(list);
}
}
Function<T, R>
1、R apply(T t) - 类型转换
public class Demo {
// String -> Integer
public static void change(String str, Function<String, Integer> fun) {
int i = fun.apply(str);
System.out.println(i);
}
public static void main(String[] args) {
change("123", s -> Integer.valueOf(s));
}
}
2、默认方法:andThen(Function) - 连续做两种类型转换
public class DemoAndThen {
// 将 "123" -> 转换成 int 后 +10
// String->Integer Function<String, Integer>
// 将 加完后的 int 值, 转换成 String, 2进制的格式
// Integer->String Function<Integer, String>
public static void change(String str, Function<String, Integer> fun1, Function<Integer, String> fun2) {
/*Integer i = fun1.apply(str);
i += 10;
String string = fun2.apply(i);
System.out.println(string);*/
String result = fun1.andThen(fun2).apply(str);
System.out.println(result);
}
public static void main(String[] args) {
change("123",
s -> Integer.valueOf(s) + 10,
i -> Integer.toBinaryString(i));
}
}
例:
/**
* String str = "ww, 20";
* 1. 将字符串截取数字年龄部分,得到字符串;
* "ww, 20" -> "20" Function<String, String>
* 2. 将上一步的字符串转换成为int类型的数字;
* "20" -> 20 Function<String, Integer>
* 3. 将上一步的int数字累加100,得到结果int数字。
* 20 -> 120 Function<Integer, Integer>
*/
public class DemoTest {
public static void change(String str, Function<String, String> fun1, Function<String, Integer> fun2, Function<Integer, Integer> fun3) {
int i = fun1.andThen(fun2).andThen(fun3).apply(str);
System.out.println(i);
}
public static void main(String[] args) {
change("ww, 20",
// "ww, 20" -> "20"
s -> s.split("[, ]+")[1],
// "20" -> 20
s -> Integer.valueOf(s),
// 20 -> 120
i -> i + 100 );
}
}
Stream流
对数组或者集合进行操作
1、获取流
// 1.单列集合获得流对象 List Set
// List -> Stream
List<String> list = List.of("aa", "bb","cc","dd");
Stream<String> streamList = list.stream();
// Set -> Stream
Set<String> set = Set.of("aa", "bb", "cc", "dd");
Stream<String> streamSet = set.stream();
// 2.多列集合 Map
Map<Integer, String> map = Map.of(1, "aa", 2, "bb", 3, "cc", 4, "dd");
// 获得map中的key
Set<Integer> keys = map.keySet();
Stream<Integer> streamKey = keys.stream();
// 获得map中 key-value对 entry
Set<Map.Entry<Integer, String>> entries = map.entrySet();
Stream<Map.Entry<Integer, String>> streamEntry = entries.stream();
// 获得value部分
Collection<String> values = map.values();
Stream<String> streamValues = values.stream();
// 3.数组获得Stream流的方式
Integer[] arrInt = {1,2,3,4,5};
Stream<Integer> streamInt = Stream.of(arrInt);
// 4.传入数组的方式可以使用可变长参数替代
Stream<Integer> streamInt2 = Stream.of(1, 2, 3, 4, 5);
2、常用API
1.void forEach(Consumer) - 终结方法 (消费)
2. Stream filter(Predicate) - 延迟方法(判断)
3. Stream map(Function<T, R>) - 延迟方法(类型转换)
4.static Stream concat(Stream, Stream) -延迟方法(将两个流拼接成一个)
public class Demo {
public static void main(String[] args) {
// 第一支队伍
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("⽯破天");
one.add("⽯中⽟");
one.add("⽼⼦");
one.add("庄⼦");
one.add("洪七公");
// 第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古⼒娜扎");
two.add("张⽆忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张⼆狗");
// 1. 第一个队伍只要名字为3个字的成员姓名;存储到⼀个新集合中。
Stream<String> oneStream = one.stream();
Stream<String> oneStream2 = oneStream.filter(name -> name.length() == 3);
// 2. 第一个队伍筛选之后只要前3个⼈;存储到⼀个新集合中。
Stream<String> oneStream3 = oneStream2.limit(3);
// 3. 第二个队伍只要姓张的成员姓名;存储到⼀个新集合中。
Stream<String> twoStream = two.stream().filter(name -> name.startsWith("张"));
// 4. 第二个队伍筛选之后不要前2个⼈;存储到⼀个新集合中。
Stream<String> twoStream2 = twoStream.skip(2);
// 5. 将两个队伍合并为⼀个队伍;存储到⼀个新集合中。
Stream<String> stream = Stream.concat(oneStream3, twoStream2);
// 6. 根据姓名创建 Person 对象;存储到⼀个新集合中。
Stream<Person> personStream = stream.map(s -> new Person(s));
// 7. 打印整个队伍的Person对象信息。
personStream.forEach(p -> System.out.println(p));
}
}
方法引用
Lambda 的简化:(对象、类、this、super、数组)
1.方法引用是对Lambda的优化, 换句话说是在Lambda内部调用了方法
2.Lambda内部调用的方法使用的参数, 就是Lambda传递进来的参数
3.方法引用也遵循了之前学习的面向对象的理论知识
@FunctionalInterface
public interface Printable {
void print(String s);
}
public class Demo {
public static void print(String s, Printable p) {
p.print(s);
}
public static void main(String[] args) {
/**
* s -> System.out.println(s)
* 1.参数s 直接传给了 println 方法使用
* 2.System.out 对象本身就是存在的
* 3.println() 这个方法本身也是存在的
* 4.println方法的参数就是 接口方法的参数
* -- 就可以简化
*/
/*print("Hello Lambda",
s -> {System.out.println(s);});*/
// 使用 方法引用 来简化Lambda
print("Hello Lambda", System.out::println);
}
}
通过对象名引用成员方法
@FunctionalInterface
public interface Printable {
void print(String s);
}
public class MyObjectMethod {
public void printUpperCase(String s) {
System.out.println(s.toUpperCase());
}
}
public class Demo {
public static void method1(String s, Printable p) {
p.print(s);
}
public static void main(String[] args) {
/* method1("hello", s -> {
// 1.先创建MyObjectMethod对象
MyObjectMethod obj = new MyObjectMethod();
// 2.调用 printUpperCase 这个方法
obj.printUpperCase(s);
});*/
// 使用方法引用来优化
/*
1.对象已经存在 obj
2.方法已经存在 printUpperCase
*/
MyObjectMethod obj = new MyObjectMethod();
method1("hello", obj::printUpperCase);
}
}
通过类名称引用静态方法
@FunctionalInterface
public interface Calcable {
int calAbs(int n);
}
public class Demo {
public static int cal(int n, Calcable c) {
return c.calAbs(n);
}
public static void main(String[] args) {
/*int t = cal(-10, n->{return Math.abs(n);});
System.out.println(t);*/
/**
* 1.方法 已经存在 abs
* 2.类存在 Math
*/
// 使用方法引用来优化
int t = cal(-10, Math::abs);
System.out.println(t);
}
}
通过super引用成员方法
public interface Greetable {
void greet(String message);
}
public class Human {
public void hi(String message) {
System.out.println("hi Human!" + message);
}
}
public class Man extends Human {
// 重写的父类的hi方法
public void hi(String message) {
System.out.println("Hi Man!" + message);
}
// 定义一个sayHello, 目的是为了传入Lambda表达式
public void sayHello(String s, Greetable g) {
g.greet(s);
}
// 这个方法的目的, 是为了调用 sayHello
public void show() {
/* sayHello("吃了吗", s->{
// 调用父类的hi方法
super.hi(s);
});*/
/**
* 1.super对象已存在
* 2.方法hi已存在
*/
sayHello("吃了吗", super::hi);
}
public static void main(String[] args) {
new Man().show();
}
}
通过this引用成员方法
public interface Richable {
void buy(String str);
}
public class Husband {
public void buyHouse(String str) {
System.out.println("在" + str + "买了一套三居室");
}
public void marry(String str, Richable ric) {
ric.buy(str);
}
public void show() {
/*marry("北京三环内", s->{
this.buyHouse(s);
});*/
/**
* this 已经存在
* buyHouse 已经存在
*/
// 方法引用优化
marry("北京三环内", this::buyHouse);
}
public static void main(String[] args) {
new Husband().show();
}
}
类的构造器引用
public interface PersonBuilder {
// 通过传入的name参数 构造一个Person对象并返回
// Person builderPerson(String name);
Person builderPerson();
}
public class Person {
private String name;
public Person() {
System.out.println("无参构造方法");
}
public Person(String name) {
this.name = name;
System.out.println("有参构造方法");
}
public String getName() {
return name;
}
}
public class Demo {
public static void build(String name, PersonBuilder builder) {
/*Person person = builder.builderPerson(name);
System.out.println(person.getName());*/
Person person = builder.builderPerson();
System.out.println(person.getName());
}
public static void main(String[] args) {
// build("ww",
// name -> new Person(name));
// 有参构造
// 构造器本身是存在的
build("ww", Person::new);
// 无参构造
/*build("ww",
() -> new Person());*/
}
}
数组的构造器引用
public interface ArrayBuilder {
// 根据n - 数组长度, 来创建一个新的数组
int[] builderArray(int n);
}
public class Demo {
public static int[] builder(int n, ArrayBuilder arrBuild) {
return arrBuild.builderArray(n);
}
public static void main(String[] args) {
// int[] array = builder(10, n -> new int[n]);
int[] array = builder(10, int[]::new);
System.out.println(array.length);
}
}