Java8 Lambda表达式

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);
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值