lambda表达式是java8提供一个重要的特性,它提供了一个正常的参数列表和一个使用这些参数的主体,它必须依附于一个特别的对象类型–函数式接口,lambda表达式语法为:
(parameters) -> expression
(parameters) -> {statements}
一、函数式接口
如果在一个接口中有且只有一个抽象方法,那么这个接口就可以当做函数式接口。Java8引入了@FunctionalInterface注解,主要用于编译错误检查,加上该注解,当接口不符合函数式接口定义的时候,编译器会报错。如果一个接口满足函数式接口的定义,不加@FunctionalInterface注解,编译器也会把该接口当做函数式接口处理。一个函数式接口如下:
@FunctionalInterface
public interface TestFunc {
void sayHi(String name);
}
测试函数式接口的简单使用:
public class TestFuncMain {
public static void main(String ... args) {
TestFunc testFunc = name -> System.out.print(name);
testFunc.sayHi("Jerry");
}
}
二、函数式接口返回实例
函数式接口返回实例的方式有两种:
- 2.1 通过lambda表达式返回接口实例
最常用的一种使用方式。返回一个Runable接口的实例示例:
public class TestLambda {
public static void main(String ... args) {
new Thread(() -> System.out.println("sub thread")).start();
System.out.println("main thread");
}
}
- 返回方法引用
返回构造器,语法:Class::new ,Class中必须要有一个显示的无参构造方法,否则会报错;
返回方法,语法:Class::method
public class Cat {
private String name;
public String getName() {
return name;
}
public Cat() {
}
public Cat(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public static Cat create(Supplier<Cat> sup) {
return sup.get();
}
public void run() {
System.out.println(name + " is running");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Cat cat = (Cat) o;
return Objects.equals(name, cat.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
测试函数示接口返回构造器和方法的示例:
public class TestReferrenceLambda {
public static void main(String ... args) {
Cat cat = Cat.create(Cat::new);
cat.setName("cat0");
List<Cat> cats = Arrays.asList(cat, new Cat("cat1"), new Cat("cat2"), new Cat("cat3"));
cats.forEach(Cat::run);
}
}
三、default关键字
default关键字是Java8中引入的关键字,在此之前,Java接口不能有方法体函数的,default关键字让接口可以有默认的方法体。
一个有方法体的Java接口如下:
public interface TestDefault {
default void defaultMethod() {
System.out.println("this is default method in interface");
}
void apply ();
}
测试示例:
public class TestDefaultImpl implements TestDefault {
@Override
public void apply() {
System.out.println("implement method of interface");
}
public static void main(String ... args) {
TestDefault testDefault = new TestDefaultImpl();
testDefault.defaultMethod();
testDefault.apply();
}
}
四、Function接口
Function接口是一个函数式接口,它包含三个默认方法和一个抽象方法。
@FunctionalInterface
public interface Function<T, R> {
// 将参数赋予相应的方法
R apply(T t);
// 默认方法,先调用入参的apply方法,再调用自身的apply方法
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
// 默认方法,先调用自身的apply方法,再调用入参的apply方法
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
// 静态方法,返回当前正在执行的方法
static <T> Function<T, T> identity() {
return t -> t;
}
}
测试示例:
public class TestFunction {
public static void main(String ... args) {
Function<Long, Long> plus2Func = (n) -> n + 2;
Function<Long, Long> doubleFunc = (n) -> n * 2;
System.out.println(plus2Func.apply(3L)); // 3 + 2
System.out.println(doubleFunc.apply(3L)); // 3 * 2
System.out.println(plus2Func.andThen(doubleFunc).apply(3L)); // (3 + 2) * 2
System.out.println(plus2Func.compose(doubleFunc).apply(3L)); // 3 * 2 + 2
System.out.println(Function.identity().compose(doubleFunc).apply(3L)); // 3 * 2
}
}
五、Consumer接口
Consumer接口也是一个函数示接口,它包含一个默认方法和一个抽象方法。
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
// 默认方法,先执行自身的accept方法,再执行入参的accept方法
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
使用示例:
public class TestComsumer {
public static void main(String ... args) {
Consumer<Integer> consumer = (n) -> {
n = n * 2;
System.out.println(n);
};
Consumer<Integer> consumer1 = (n) -> {
n = n + 5;
System.out.println(n);
};
consumer.andThen(consumer1).accept(10);
}
}
六、Predicate接口
Predicate接口包含三个默认方法,一个静态方法和一个抽象方法。
@FunctionalInterface
public interface Predicate<T> {
// 返回布尔值,用于校验
boolean test(T t);
// 默认方法,接收一个Predicate参数,用于判断两个条件是否都成立
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
// 默认方法,对判断取反
default Predicate<T> negate() {
return (t) -> !test(t);
}
// 默认方法,接收一个Predicate参数,用于判断两个条件是否至少有一个成立
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
测试示例:
public class TestPredicate {
public static void main(String... args) {
System.out.println(judge("abcde", (p) -> p.startsWith("a")) );
System.out.println(judgeNo("abcde", (p) -> p.startsWith("a")) );
System.out.println(judgeAnd("abcde", (p) -> p.startsWith("a"), (p) -> p.length() > 10) );
System.out.println(judgeOr("abcde", (p) -> p.startsWith("a"), (p) -> p.length() > 10) );
System.out.println(Predicate.isEqual("test").test("test"));
System.out.println(Predicate.isEqual("test").test("test1"));
}
private static boolean judge(String str, Predicate<String> condition) {
if (null == str) {
return false;
}
return condition.test(str);
}
private static boolean judgeNo(String str, Predicate<String> condition) {
if (null == str) {
return false;
}
return condition.negate().test(str);
}
private static boolean judgeAnd(String str, Predicate<String> condition1, Predicate<String> condition2) {
if (null == str) {
return false;
}
return condition1.and(condition2).test(str);
}
private static boolean judgeOr(String str, Predicate<String> condition1, Predicate<String> condition2) {
if (null == str) {
return false;
}
return condition1.or(condition2).test(str);
}
}
七、Stream工具类
Java8中引入了对集合数据进行处理的Stream流,主要用于集合数据的筛选、过滤、计算等操作。它不会存储和修改元素,遍历结束即消费结束。
public class TestStream {
public static void main(String ... args) {
createStream();
streamFilter();
streamMap();
streamSort();
streamStop();
streamReduce();
streamCollect();
}
// 创建Stream流
private static void createStream() {
List<String> list = Arrays.asList("abc", "cde", "hij");
Stream<String> stream1 = list.stream(); // 通过集合创建
Stream<String> stream2 = list.parallelStream(); // 通过集合创建
stream1.forEach(System.out::println);
stream2.forEach(System.out::println);
Stream<Integer> strea3 = Stream.iterate(2, (x) -> x * 2).limit(5); // 通过函数创建
strea3.forEach(System.out::println);
Stream<Double> stream4 = Stream.generate(Math::random).limit(5); // 通过函数创建
stream4.forEach(System.out::println);
Stream<String> stream5 = Stream.of("abc", "def"); // 通过值创建
Stream<String> stream6 = Arrays.stream(strings); // 通过数组创建
}
// 中间方法:filter、distinct、limit、skip
// filter:在流中筛选一些符合要求的元素
// distinct:在流中利用equals方法去除某些相同的元素
// limit: 在流中数据达到最大值时截断流
// skip: 丢弃流中的前n个元素
private static void streamFilter() {
List<Cat> cats = Arrays.asList(new Cat("abc"), new Cat("abc"), new Cat("def"), new Cat("ghi"), new Cat("lmn1"));
cats.stream().filter((cat) -> cat.getName().length() < 4).distinct().limit(3).skip(1).forEach(System.out::println);
}
// 映射:map、flatmap
// map: 对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素。
// flatMap:和map类似,不同的是其每个元素转换得到的是Stream对象,会把子Stream中的元素压缩到父集合中
private static void streamMap() {
List<Cat> cats = Arrays.asList(new Cat("abc"), new Cat("abc"), new Cat("def"), new Cat("ghi"), new Cat("lmn1"));
List<Cat> cats2 = Arrays.asList(new Cat("lmnabcde"));
cats.stream().map((cat) -> cat.getName() + " -> feeded").forEach(System.out::println);
Stream.of(cats, cats2).flatMap((list) -> list.stream()).map((cat) -> cat.getName() + " -> not feeded").forEach(System.out::println);
}
// 排序:sort、sorted
// sort: 按照自然规则排序
// sorted: 按照给定规则排序
private static void streamSort() {
List<Cat> cats = Arrays.asList(new Cat("abc"), new Cat("abc"), new Cat("def"), new Cat("ghi"), new Cat("lmn1"));
cats.stream().map(cat -> cat.getName().length()).sorted().forEach(System.out::println);
cats.stream().sorted(Comparator.comparing(cat -> -1 * cat.getName().length())).forEach(System.out::println);
}
// 终止操作
// count: 返回流中的元素个数
// allMatch: 流中的元素是否都满足Predicate条件
// anyMatch: 流中是否有元素满足Predicate条件
// max: 返回Comparator比较后的最大值
private static void streamStop() {
List<Cat> cats = Arrays.asList(new Cat("abc"), new Cat("abc"), new Cat("def"), new Cat("ghi"), new Cat("lmn1"));
System.out.println(cats.stream().count());
System.out.println(cats.stream().allMatch((cat) -> cat.getName().equals("abc")));
System.out.println(cats.stream().anyMatch((cat) -> cat.getName().equals("abc")));
System.out.println(cats.stream().max((cat1, cat2) -> cat1.getName().length() - cat2.getName().length()));
}
// 归约
// reduce(b): 将流中的元素经过指定运算,折叠成一个元素输出
// reduce(a, b): 将流中的元素经过指定运算,折叠成一个元素输出,指定起始值a
private static void streamReduce() {
List<Cat> cats = Arrays.asList(new Cat("abc"), new Cat("abc"), new Cat("def"), new Cat("ghi"), new Cat("lmn1"));
System.out.println(cats.stream().map(cat -> cat.getName().length()).reduce(Integer::sum));
System.out.println(cats.stream().map(cat -> cat.getName().length()).reduce(3, Integer::sum));
}
// collect,将流转换成集合的形式
private static void streamCollect() {
List<Cat> cats = Arrays.asList(new Cat("abc"), new Cat("abc"), new Cat("adef"), new Cat("aghi"), new Cat("lmn1"));
Set<Cat> set = cats.stream().filter(cat -> cat.getName().startsWith("a")).collect(Collectors.toSet());
set.stream().forEach(System.out::println);
}
}