package lambdasinaction.chap3;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.function.*;
import java.util.stream.Collectors;
/**
* lambda表达式的简单示例
*/
public class Lambdas {
public static void main(String... args) throws Exception {
/*
Predicate: 谓词,Supplier:供应,Consumer:消费
>>> 常用函数式接口
函数式接口 函数描述符 原始类型初始化
Predicate<T> T->Boolean IntPredicate,LongPredicate,DoublePredicate
Consumer<T> T->void IntConsumer,LongConsumer,DoubleConsumer
Function<T,R> T->R IntFunction<R>,IntToDoubleFunction,IntToLongFunction
LongFunction<R>,LongToIntFunction,LongToDoubleFunction
DoubleFunction<R>,DoubleToIntFunction,DoubleToLongFunction
ToIntFunction<R>,ToDoubleFunction<R>,ToLongFunction<R>
Supplier<T> ()->T BooleanSupplier,IntSupplier,DoubleSupplier,LongSupplier
UnaryOperator<T> T->T IntUnaryOperator,LongUnaryOperator,DoubleUnaryOperator
BinaryOperator<T> (T,T)->T IntBinaryOperator,DoubleBinaryOperator,LongBinaryOperator
BiPredicate<L,R> (L,R)->boolean
BiConsumer<T,U> (T,U)->void ObjIntConsumer<T>,ObjLongConsumer<T>,ObjDoubleConsumer<T>
BiFunction<T,U,R> (T,U)->R ToIntBiFunction<T,U>
ToDoubleBiFunction<T,U>
ToLongBiFunction<T,U>
>>> 应用举例
使用案例 Lambda例子 对应函数式接口
1. (List<String> list)->list.isEmpty()
T->Boolean Predicate<List<String>>
2. ()->new Apple(10)
()->T Supplier<Apple>
3. (Apple apple)->System.out.println(apple.getWeight())
(T)->void Consumer<Apple>
4. (String s)->s.Length()
T->R Function<String,Integer> / ToIntFunction<String>
5. (int a, int b)->a*b
(T,T)->T BinaryOperator<Integer> / IntBinaryOperator
6. (Apple a1, Apple a2)->a1.getWeight().compareTo(a2.getWeight())
(T,T,R)-> BiFunction<Apple,Apple,Integer> / ToIntFunction<Apple,Apple> /
Comparator<Apple>
*/
Predicate<List<String>> predicate = list -> list.isEmpty(); //定义逻辑
// predicate.negate() //取反
boolean test_result = predicate.test(new ArrayList<>()); //执行逻辑
System.out.println("predicate: " + test_result);
ToIntFunction<String> toIntFunction = s -> s.length(); //这里不能写String::length
int abc_length = toIntFunction.applyAsInt("abc");
int abcd_length = getStrLength("abcd", String::length); //作为参数,String::length可以推断
System.out.println("abc: " + abc_length + ", abcd:" + abcd_length);
Callable<Integer> callable = () -> 42;
Integer callable_result = callable.call();
System.out.println("callable: " + callable_result);
List<String> list = new ArrayList<>();
//以下两个是等价的
Predicate<String> predicate1 = s -> list.add(s); //返回了一个boolean
Consumer<String> consumer = s -> list.add(s); //返回void
predicate1.test("aa");
consumer.accept("bb");
System.out.println("list: " + list);
/*
>>> 方法引用 与 类型推断
1.::方法引用只在作为参数时使用
三类方法引用:
1.指向静态方法的引用,如Integer:parseInt
2.指向任意类型实例方法的引用,如String::length
3.指向现有对象的实例方法的引用,如obj::getValue
例子:
(Apple a)->a.getWeight() Apple::getWeight
()->Thread.currentThread().dumpStack() Thread.currentThread()::dumpStack
(str, i)->str.substring(i) String::substring
(String s)->System.out.println(s) System.out::println
*/
//System.out::println的签名是:接收String,没有返回
myPrint("test_print", System.out::println); //输出test_print
String r1 = mySub2("abcdef", 2, String::substring); //"abcdef".substring(2)
System.out.println(r1);
// mySub21("abcde",2,String::substring); //不能用String::substring,因mySub21签名是:接收一个参数Integer,返回String,这里无法推断
String str = "abcdef";
String r2 = mySub21(str, 2, str::substring); //这里同上,第一个参数的作用已写出,容易自动推断第二个参数
System.out.println(r2);
String r3 = mySub22(str, "eee", str::concat); //同上. 类型推断首先参考的是参数顺序
System.out.println(r3);
// mySub22(str,"eee",s->s.concat(?)) //无法写出
// mySub3("abcdef", 2, 3, String::substring);
String r4 = mySub3(str, 2, 3, String::substring);
System.out.println(r4);
String r5 = myConcat("abcdef", "_gh", String::concat);
System.out.println(r5);
List<String> list1 = Arrays.asList("a", "b", "A", "B");
list1.sort((s1, s2) -> s1.compareToIgnoreCase(s2));
System.out.println(list1);
List<String> list2 = Arrays.asList("a", "b", "A", "B");
list2.sort(String::compareToIgnoreCase);
System.out.println(list2);
List<String> list3 = Arrays.asList("a", "b", "A", "B");
list3.sort(Comparator.comparing(s -> s.toLowerCase())); //不加toLowerCase,则是大写在前
System.out.println(list3);
/*
>>> 构造函数
*/
Supplier<Apple> appleSupplier = Apple::new; //无参构造函数
Apple apple1 = appleSupplier.get();
System.out.println(apple1);
BiFunction<Integer, String, Apple> appleBiFunction = Apple::new; //有参构造函数
Apple apple2 = appleBiFunction.apply(2, "blue");
System.out.println(apple2);
/*
>>> 复合Lambda
*/
List<Apple> appleList = Arrays.asList(new Apple(20, "blue"),
new Apple(150, "white"),
new Apple(10, "black"),
new Apple(150, "blue"));
appleList.sort(Comparator.comparing(Apple::getWeight)
.reversed()
.thenComparing(Apple::getColor));
System.out.println(appleList);
Predicate<Apple> p1 = (a) -> a.getWeight() >= 20;
Predicate<Apple> p2 = a -> a.getColor().equals("blue");
//重量大于等于20,且颜色是蓝色
Predicate<Apple> pp1 = p1.and(p2);
List<Apple> list4 = appleList.stream().filter(pp1).collect(Collectors.toList());
System.out.println(list4);
//(重量大于等于20且颜色是蓝色)或(黑色)
Predicate<Apple> pp2 = pp1.or(a -> a.getColor().equals("black"));
List<Apple> list5 = appleList.stream().filter(pp2).collect(Collectors.toList());
System.out.println(list5);
/*
>>> 复合函数
*/
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
//g(f(x)): 先计算f, 结果参与g的计算
Function<Integer, Integer> h = f.andThen(g);
Integer rr1 = h.apply(1); //4
System.out.println(rr1);
//f(g(x)):先计算g,结果参与f的计算
Function<Integer, Integer> h2 = f.compose(g);
Integer rr2 = h2.apply(1); //3
System.out.println(rr2);
// Simple example
// Runnable拥有一个无参函数,且没有返回值
// 这里省略了匿名类和方法名, 用匿名类和下面的代码类比,相对好理解
Runnable r = () -> System.out.println("Hello!");
r.run();
// Filtering with lambdas
List<Apple> inventory = Arrays.asList(new Apple(80, "green"), new Apple(155, "green"), new Apple(120, "red"));
// [Apple{color='green', weight=80}, Apple{color='green', weight=155}]
// 接口接收Apple类型的参数,返回boolean
List<Apple> greenApples = filter(inventory, (Apple a) -> "green".equals(a.getColor()));
System.out.println(greenApples);
// Comparator 接收两个参数,返回int
Comparator<Apple> c = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
// [Apple{color='green', weight=80}, Apple{color='red', weight=120}, Apple{color='green', weight=155}]
inventory.sort(c); //排序
System.out.println(inventory);
}
/**
* 接收String,Integer,返回新的String
*/
public static String mySub2(String s, int i, BiFunction<String, Integer, String> consumer) {
return consumer.apply(s, i);
}
public static String mySub21(String s, int i, Function<Integer, String> consumer) {
return s + ": " + consumer.apply(i);
}
public static String mySub22(String s, String s2, Function<String, String> consumer) {
return s + ": " + consumer.apply(s2);
}
/**
* 接收String, Integer, Integer, 返回新的String
*/
public static String mySub3(String s, int start, int end, BiFunction3<String, Integer, Integer, String> consumer) {
return consumer.apply(s, start, end);
}
/**
* 接收String,String,返回String
*
* @param s
* @param s2
* @param consumer
* @return
*/
public static String myConcat(String s, String s2, BiFunction<String, String, String> consumer) {
return consumer.apply(s, s2);
}
/**
* 对字符串进行应用,且不返回
*
* @param s
* @param consumer
*/
public static void myPrint(String s, Consumer<String> consumer) {
consumer.accept(s);
}
public static Integer getStrLength(String str, ToIntFunction<String> toIntFunction) {
return toIntFunction.applyAsInt(str);
}
public static List<Apple> filter(List<Apple> inventory, ApplePredicate p) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
}
public static class Apple {
private int weight = 0;
private String color = "";
public Apple() {
}
public String calc(String a, String b) {
return a + "_" + b;
}
public Apple(int weight, String color) {
this.weight = weight;
this.color = color;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String toString() {
return "Apple{" +
"color='" + color + '\'' +
", weight=" + weight +
'}';
}
}
interface ApplePredicate {
public boolean test(Apple a);
}
}