lamda表达式和stream操作

写在前面

在jdk8中为了简单对象的创建工作,以及集合的相关操作,分别新增了lambda表达式和stream流式操作,本文就起来看下。

1:lambda表达式

1.1:什么是lambda表达式

可以认为是一种匿名函数,格式如下:

完整格式:
    (parameters) -> {statements;}
如果是statement只有一行则可以省略{}:
    (parameters) -> statements

如下简单的只有一个表达式例子:

1,没有参数,直接返回5
    () -> 5
2,接受一个数字类型参数,返回其2倍的值
    x -> 2*x
3,接收两个参数,返回他们的差值
    (x, y) -> x-y
4,接收两个int类型整数,返回他们的和
    (int x, int y) -> x+y
5,接收一个string对象,并在控制台打印,不返回任何值
    (String s) -> System.out.println(s)

1.2:核心接口

1.2.1:Predicate

判断真假的函数式接口,源码如下:

@FunctionalInterface // 函数是接口注解,仅仅是个标记而已,没有该注解也无所谓,有更明确
public interface Predicate<T> {
    // 基于给定的值t,返回真假
    boolean test(T t);

    // &短路操作,返回两个predicate的&结果,如果想要n个&的话,多次调用and即可
    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);
    }

    // ||短路操作
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    // 判断是否和目标对象相等的Predicate
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

接下来看下实例。

  • test
Predicate<Integer> p1 = (t) -> { // 这里是test方法的方法体
    t = t * 2;
    return t > 100;
};
System.out.println(p1.test(99));

运行:

true
  • and
Predicate<Integer> p1 = (t) -> { // 这里是test方法的方法体
    t = t * 2;
    return t > 100;
};
//        System.out.println(p1.test(99));
Predicate<Integer> p2 = (t) -> { // 这里是test方法的方法体
    t = t / 2;
    return t > 99;
};
Predicate<Integer> p3 = p1.and(p2);
/*
相当于如下代码:
{ // 这里是test方法的方法体
    t = t * 2;
    return t > 100;
} && { // 这里是test方法的方法体
    t = t / 2;
    return t > 99;
}
    */
System.out.println(p3.test(600));

多次and:

Predicate<Integer> p1 = (t) -> { // 这里是test方法的方法体
    t = t * 2;
    return t > 100;
};
//        System.out.println(p1.test(99));
Predicate<Integer> p2 = (t) -> { // 这里是test方法的方法体
    t = t / 2;
    return t > 99;
};
Predicate<Integer> p2_1 = (t) -> { // 这里是test方法的方法体
    t = t / 2;
    return t > 999;
};
Predicate<Integer> p3 = p1.and(p2).and(p2_1);
System.out.println(p3.test(600));
  • negate
Predicate<Integer> p4 = (t) -> { // 这里是test方法的方法体
    t = t / 2;
    return t > 999;
};
Predicate<Integer> negate = p4.negate();
System.out.println(negate.test(888));

运行:

true

Process finished with exit code 0
  • or
Predicate<Integer> p4 = (t) -> { // 这里是test方法的方法体
    t = t / 2;
    return t > 999;
};
Predicate<Integer> p4_1 = (t) -> { // 这里是test方法的方法体
    t = t * 2;
    return t > 688;
};
Predicate<Integer> or = p4.or(p4_1);
System.out.println(or.test(100));

运行:

false

Process finished with exit code 0

1.2.2:Function

对接收一个参数,并根据该参数返回一个结果操作的抽象接口,如下:

@FunctionalInterface
public interface Function<T, R> {

    // 根据入参t执行逻辑,并返回值R
    R apply(T t);

    // 组合两个Function,使用第一个Function apply的返回值,作为第二个Function的入参,再apply
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    // 同compose但是2个Functin apply的顺序相反
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    // 返回一个永远直接返回入参的Function
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

看下例子。

  • apply
Function<String, String> f1 = (v) -> {
    return v + "___===";
};
System.out.println(f1.apply("张三"));

运行:

张三___===

Process finished with exit code 0
  • compose
Function<String, String> f1 = (v) -> {
    return v + "A";
};
//        System.out.println(f1.apply("张三"));
Function<String, String> f2 = (v) -> {
    return v + "B";
};
Function<String, String> compose = f1.compose(f2);
System.out.println(compose.apply("张三"));

运行:

张三BA

Process finished with exit code 0

多个compose:

Function<String, String> f1 = (v) -> {
    return v + "A";
};
//        System.out.println(f1.apply("张三"));
Function<String, String> f2 = (v) -> {
    return v + "B";
};
Function<String, String> f3 = (v) -> {
    return v + "C";
};
Function<String, String> compose = f1.compose(f2).compose(f3);
System.out.println(compose.apply("张三"));

运行:

张三CBA

Process finished with exit code 0
  • andThen
Function<String, String> f1 = (v) -> {
    return v + "A";
};
//        System.out.println(f1.apply("张三"));
Function<String, String> f2 = (v) -> {
    return v + "B";
};
Function<String, String> f3 = (v) -> {
    return v + "C";
};
Function<String, String> compose = f1.andThen(f2).andThen(f3);
System.out.println(compose.apply("张三"));

运行:

张三ABC

Process finished with exit code 0
  • identity
Function<String, String> f1 = Function.identity();
System.out.println(f1.apply("照镜子!!!"));

运行:

照镜子!!!

Process finished with exit code 0

1.2.3:Consumer

对只接收一个入参,并对该参数执行操作,但是不需要返回值场景的抽象,源码如下:

@FunctionalInterface
public interface Consumer<T> {

    // 对给定的入参t执行操作,但不需要返回值
    void accept(T t);

    // 返回 一次执行两个Consumer的accept 的Consumer
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

看下例子。

  • accept
Consumer<String> c1 = (v) -> {
    System.out.println("执行业务操作了。。。" + v);
};
c1.accept("follow your heart!!!");

运行:

执行业务操作了。。。follow your heart!!!

Process finished with exit code 0
  • andThen
Consumer<String> c1 = (v) -> {
    System.out.println("执行业务操作了A" + v);
};
Consumer<String> c2 = (v) -> {
    System.out.println("执行业务操作了B" + v);
};
c1.andThen(c2).accept("lab");

运行:

执行业务操作了Alab
执行业务操作了Blab

Process finished with exit code 0

1.2.4:Supplier

对于不需要任何的入参,根据特定外部条件返回一个值场景的抽象,比如返回当前的时间戳,源码如下:

@FunctionalInterface
public interface Supplier<T> {
    // 获取特定业务场景下的某个结果
    T get();
}

例子:

Supplier<Long> supplier = () -> {
    return System.currentTimeMillis();
};
System.out.println(supplier.get());

运行:

1688636413386

Process finished with exit code 0

1.3:例子

代码:

// 泛型 T 必须是 Serializable&Comparable&Collection 必须是这三个接口的实现类
public class LambdaDemo<T extends Serializable&Comparable&Collection> {
    
    public static void main(String args[]){
        LambdaDemo demo = new LambdaDemo();

        // Java 8以前的写法,当然现在也可以这样写,只是相对比较麻烦
        MathOperation op2 = new MathOperation<Integer>() {
            @Override
            public Integer operation(int a, int b) {
                return a+b;
            }
        };
        // 参数不写数据类型,直接返回1,生意省略{}和return,相当于MathOperation op1 = (int a, int b) -> { return 1; };
        MathOperation op1 = (a, b) -> 1;
        // 参数声明类型,将两个入参之和作为结果返回,单语句,省略{}和return,相当于MathOperation addition = (int a, int b) -> {return a + b;};
        MathOperation addition = (int a, int b) -> a + b;
        // 参数声明类型,将两个入参之差作为结果返回,单语句,省略{}和return,相当于MathOperation addition = (int a, int b) -> {return a - b;};
        MathOperation subtraction = (int a, int b) -> a - b ;
        // 大括号中的返回语句
        MathOperation multiplication = (int a, int b) -> { 
            //int c = 1000;
            return a * b;// + c;
        };
        // 没有大括号及返回语句
        MathOperation division = (int a, int b) -> a / b;
        
        System.out.println("10 + 5 = " + demo.operate(10, 5, addition));
        System.out.println("10 - 5 = " + demo.operate(10, 5, subtraction));
        System.out.println("10 x 5 = " + demo.operate(10, 5, multiplication));
        System.out.println("10 / 5 = " + demo.operate(10, 5, division));
        System.out.println("10 ^ 5 = " + demo.operate(10, 5, (a, b) -> Math.pow(a,b)));

        // 无参数,只有一个表达式,可以省略{},相当于Runnable task = () -> { System.out.println(1111); };
        Runnable task = () -> System.out.println(1111);
        // 不用括号
        GreetingService greetService1 = message ->
                System.out.println("Hello " + message);
        // 用括号
        GreetingService greetService2 = (message) -> {
            System.out.println(message);
        };
        // 只有一个表达式并且调用的out的方法,可以通过::简写,并且省略参数声明和{},完整写法:GreetingService greetService3 = (message) -> { System.out.println(message); };
        GreetingService greetService3 = System.out::println;
        // 循环+3输出
        Arrays.asList(1,2,3).forEach(x -> System.out.println(x+3));
        // 循环调用LambdaDemo.println静态方法
        Arrays.asList(1,2,3).forEach( LambdaDemo::println );
        
        greetService1.sayMessage("kimmking");
        greetService2.sayMessage("Java");
        greetService3.sayMessage("CuiCuilaoshi");
    }
    
    private static void println(int x) {
        System.out.println(x+3);
    }

    @FunctionalInterface
    interface MathOperation<T> {
        T operation(int a, int b); // 返回类型+函数名+参数类型的列表
    }
    
    interface GreetingService {
        void sayMessage(String message);
    }
    
    private <T> T operate(int a, int b, MathOperation<T> mathOperation){
        return mathOperation.operation(a, b);
    }
    
}

运行:

10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
10 ^ 5 = 100000.0
4
5
6
4
5
6
Hello kimmking
Java
CuiCuilaoshi

Process finished with exit code 0

2:stream

流是来自数据源的元素队列,并支持以链式的方式进行聚合操作的抽象定义。

数据源:可以是集合,数组,I/O等
元素:单个数据
聚合操作:map,reduce,sort,limit等

2.1:操作类型

stream的操作分为两类,分别是中间操作和终止操作,中间操作就是返回的依然是流,还可以继续执行其他的中间操作,终止操作是获取了最终的一个结果。

2.1.1:中间操作

中间操作就是返回的依然是流,还可以继续执行其他的中间操作,主要包括如下的操作:

选择与过滤
    1:filter(Predicate p) 排除元素
    2:distinct() 通过元素的hashCode和equals()排除元素
    3:limit(long maxSize) 截断流,使其元素不超过给定数量
    4:skip(long n) 跳过元素,返回一个跳过了前n个元素的流,若流中元素不足n个,则返回一个空流
映射
    1:map(Function f) 转换元素的值到另一个值
    2:mapToDouble(ToDoubleFunction f) 将每个元素转换为Double,并返回DoubleStream
    3:mapToInt(ToIntFunction f) 将每个元素转换为int,并返回IntStream
    4:mapToLong(ToLongFunction f) 将每个元素转换为long,并返回LongStream
    5:flatMap(Function f) 平铺为一个流,即如果中间的是集合,则展开
排序
    1:sorted() 产生一个新流,按照自然顺序排序
    2:sorted(Comparator comp) 产生一个新流,其中按照比较器的顺序排序

2.1.2:终止操作

终止操作是获取了最终的一个结果,主要包括如下操作:

查找与匹配
    1:allMatch(Predicate predicate) 是否所有元素都会返回true
    2:anyMatch(Predicate predicate) 至少一个元素返回true
    3:noneMatch(Predicate predicate) 所有元素都返回fasle,即都不匹配
    4:findFirst() 返回第一个元素,注意返回的是Option,避免NPE
    5:findAny() 返回随机的一个元素,注意返回的是Option,避免NPE
    6:count() 获取元素的总数
    7:max() 获取最大值
    8:min() 获取最小值
规约
    reduce 需要初始值
收集collect
    collect(Collections.toList()) 转换为List集合
    collect(Collections.toSet()) 转换为Set集合
    collect(toCollection(Supplier collectionFactory)) 转换为集合,泛型C确定哪种集合

我们来看下其中的Collections.toList(),源码如下:

public static <T>
Collector<T, ?, List<T>> toList() {
    return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                (left, right) -> { left.addAll(right); return left; },
                                CH_ID);
}

CollectorImp前两个参数用了最简单的写法,完整写法如下:

return new CollectorImpl<>((Supplier<List<T>>) () -> new ArrayList<>(), (List<T> a, T b) -> { a.add(b); },
                            (left, right) -> { left.addAll(right); return left; },
                            CH_ID);

或者第一个参数不显式设置强转,通过第二个参数a就已经确定泛型的类型了,如下:

return new CollectorImpl<>(() -> new ArrayList<>(), (List<T> a, T b) -> { a.add(b); },
        (left, right) -> { left.addAll(right); return left; },
        CH_ID);

2.2:例子

测试代码:

public class StreamDemo {

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(4, 2, 3, 5, 1, 2, 2, 7, 6);
        // 中间操作fillter
        System.out.println("fillter: " + list.stream().parallel().filter((v) -> v > 5).collect(Collectors.toList()));
        // distinct去重
        System.out.println("distinct: " + list.stream().parallel().distinct().collect(Collectors.toList()));
        // limit 限制元素个数
        System.out.println("limit: " + list.stream().limit(3).collect(Collectors.toList()));
        // skip 跳过前n个元素
        System.out.println("skip: " + list.parallelStream().skip(7).collect(Collectors.toList()));
        // map 拼加A转成字符串
        System.out.println("map: " + list.parallelStream().map((v) -> v + "A").collect(Collectors.toList()));
        // mapToDouble 转Double
        System.out.println("mapToDouble: " + list.parallelStream().mapToDouble((v) -> v).boxed().collect(Collectors.toList()));
        // mapToInt 转Integer
        System.out.println("mapToInt: " + list.parallelStream().mapToInt((v) -> v).boxed().collect(Collectors.toList()));

        // flatMap
        List<List<String>> list111 = new ArrayList<>();
        List<String> listA = new ArrayList<>();
        listA.add("A1");
        listA.add("A2");
        List<String> listB = new ArrayList<>();
        listB.add("B1");
        listB.add("B2");
        list111.add(listA);
        list111.add(listB);
        System.out.println("flatMap: " + list111.stream().flatMap(v -> v.stream()).collect(Collectors.toList()));

        // sorted
        // List list = Arrays.asList(4, 2, 3, 5, 1, 2, 2, 7, 6);
        System.out.println("sorted: " + list.stream().parallel().sorted().collect(Collectors.toList()));
        // sorted(Comparator)
        System.out.println("sorted(Comparator): " + list.stream().sorted((o1, o2) -> o2 - o1).collect(Collectors.toList()));

        // 终止操作 anyMatch
        System.out.println("anyMatch: " + list.stream().anyMatch(v -> v > 6));
        // 终止操作 allMatch
        System.out.println("allMatch: " + list.stream().allMatch(v -> v < 0));

        // reduce 求和 初始值给0
        // 计算过程 0+list[0] = result1 result1+list[1]=result2 ...
        System.out.println("reduce 求和 初始值给0 : " + list.stream().reduce(0, (v1, v2) -> v1 + v2));

        // reduce 求积 初始值给1
        // 计算过程 1*list[0] = result1 result1*list[1]=result2 ...
        System.out.println("reduce 求积 初始值给1 : " + list.stream().reduce(1, (v1, v2) -> v1 * v2));

        // findFirst
        System.out.println("findFirst: " + list.stream().findFirst().get());
        // findAny
        System.out.println("findAny: " + list.stream().findAny().get());
        // max
        System.out.println("max: " + list.stream().max((v1, v2) -> v1 - v2).get());

        // count 大于4的个数
        System.out.println("count 大于4的个数: " + list.stream().filter(v -> v > 4).count());
    }
}

运行:

fillter: [7, 6]
distinct: [4, 2, 3, 5, 1, 7, 6]
limit: [4, 2, 3]
skip: [7, 6]
map: [4A, 2A, 3A, 5A, 1A, 2A, 2A, 7A, 6A]
mapToDouble: [4.0, 2.0, 3.0, 5.0, 1.0, 2.0, 2.0, 7.0, 6.0]
mapToInt: [4, 2, 3, 5, 1, 2, 2, 7, 6]
flatMap: [A1, A2, B1, B2]
sorted: [1, 2, 2, 2, 3, 4, 5, 6, 7]
sorted(Comparator): [7, 6, 5, 4, 3, 2, 2, 2, 1]
anyMatch: true
allMatch: false
reduce 求和 初始值给0 : 32
reduce 求积 初始值给1 : 20160
findFirst: 4
findAny: 4
max: 7
count 大于4的个数: 3

写在后面

参考文章列表

你可能感兴趣的:(Java高级开发进阶教程,lambda,stream操作)