Java 入门 (十三)

Lambda 表达式

作用

为了简化匿名内部类的书写

本质

本质就是一个接口的对象

前提

必须是一个函数式接口。

注意:函数式接口就是只有一个抽象方法的接口。函数式接口都有一个统一的注释@FunctonalInterface

格式

(参数列表)->{}
格式的解释:
(参数列表):这个是放方法参数的方法
->:就是一个符号,表明了这是个Lambda表达式
{}:函数式接口中的抽象方法的方法体,也叫Lambda体

实例

package top.zunmx.u1;

// ALC-Master
@FunctionalInterface // 只能有一个抽象方法
interface A {
    public abstract void a();

//  public abstract void b();
    public static void b() {
        System.out.println("A-b");
    }
}

public class Demo {
    public static void main(String[] args) {
//          AnonymousInnerClass?
            new A() {
                @Override
                public void a() {
                    System.out.println("匿名内部类方式!");
                }
            }.a();

//          Lambda
        A a = ()->{
            System.out.println("Lambda表达式方式");
        };
        a.a();
    }
}
package top.zunmx.u1;
@FunctionalInterface
interface B{
    public abstract void show(String text);
}
// ALC-Master
public class Demo2 {

    public static void main(String[] args) {
        B b = (sss)->{
            System.out.println(sss);
        };
        b.show("123");

        B c = abc ->{
            System.out.println(abc);
        };
        c.show("321");
    }
}
package top.zunmx.u1;

@FunctionalInterface
interface C {
    public abstract void show(int a, int b);
}

// ALC-Master
public class Demo3 {

    public static void main(String[] args) {
        C c = (a, b) -> {
            System.out.println(a + b);
        };
        c.show(5,3);
    }
}
package top.zunmx.u1;

// ALC-Master
interface D {
    public abstract int show(int a, int b);
}

public class Demo4 {
    public static void main(String[] args) {
        D d = (a, b) -> {
            return a + b;
        };
        System.out.println(d.show(3, 7));
    }
}
package top.zunmx.u1;

// 大括号和return可以要么省略,要么就全部保留
interface D {
    public abstract int show(int a, int b);
}
public class Demo4 {
    public static void main(String[] args) {
        D d = (a, b) ->  a + b;
        System.out.println(d.show(3, 7));
    }
}
package top.zunmx.u1;

// 如果大括号只有一条语句,还是省
interface E {
    public abstract void show(String s);
}
public class Demo5 {
    public static void main(String[] args) {
        E e = (abc) -> System.out.println("hello:" + abc);
        e.show("!!!");
    }
}

注意事项

  1. 如果小括号中只有一个参数,那么可以省略小括号
  2. 如果打括号中只有一条输出语句,那么可以省略大括号
  3. 如果大括号中只有一条语句,并且是return 语句,那么可以同时省略return和大括号。

函数式接口

接口中只有一个抽象方法

注解:@FunctionalInterface

根据需求我们得出了以上的方法声明,但是这个方法声明是有问题的。因为在之前我们写一个方法的时候,只需要将参数a和b传递进去就可以使用了,但是现在我们不仅需要传递参数a和b,还需要传入对a和b的操作(也就是对a和b操作的方法),但是方法上是不能传递方法当做参数的,怎么办?Java官方给了折中的方法,我们不用在方法上传递方法了,而是在方法上传递一个接口(传递的是一个接口,实际上传递的是该接口的对象),接口中有抽象方法,可以让这个抽象方法做对a和b的操作。(注意:因为接口中的抽象方法必须要被重写才能使用,可以在方法重写的时候让它不同的功能)

常见的函数式接口

  • 消费型接口---Consumer
  • 供给型接口---Supplier
  • 函数型接口---Function
  • 断言型接口---Predicate

消费性接口Consumer

只接收数据并处理数据,但是不产生返回值

构造

public interface Consumer<T>;

方法

void accept(T t) ;
//对给定的参数执行此操作。 

实例

package top.zunmx.d1;

import java.util.function.Consumer;

// ALC-Master

//function 1_1  start  创建一个子类,实现Consumer接口
class ConsumerImpl implements Consumer<Integer> {
    @Override
    public void accept(Integer t) {
        System.out.println("F1小明拿了" + t + "元钱啊,买了个大宝剑");
    }
}

// function1_1 end
public class Demo2 {
    public static void wasteMoney(int money, Consumer<Integer> con) { // 要的是接口,实际上要的是该接口的对象昂
        con.accept(money);
    }

    public static void main(String[] args) {
        // function 1_2 创建要给子类实现Consumer接口
        ConsumerImpl ci = new ConsumerImpl();
        wasteMoney(100, ci);
        // function 1_2 end

        // function 2 使用匿名内部类
        Consumer<Integer> consumer = new Consumer<Integer>() {
            public void accept(Integer t) {
                System.out.println("F2小明拿了" + t + "元钱啊,买了个大宝剑");
            };
        };
        wasteMoney(200, consumer);
        // function 2 end

        // function 3 使用lambda 表达式
        Consumer<Integer> con = (x) -> System.out.println("F3小明拿了" + x + "元钱啊,买了个大宝剑");
        wasteMoney(300, con);
        // function 3 end
        // function 4 复合Lambda
        wasteMoney(400, x -> System.out.println("F4小明拿了" + x + "元钱啊,买了个大宝剑"));
        // function 4 end
    }
}

供给型接口Supplier

构造

public interface Supplier<T>

接口中的抽象方法必须要参数,而只产生返回值

方法

T get() 
获得结果。  

实例

package top.zunmx.d2;

import java.util.ArrayList;
import java.util.Random;
import java.util.function.Supplier;

// ALC-Master
public class Demo {
    public static ArrayList<Integer> getter(int size, Supplier<Integer> sal) {

        ArrayList<Integer> al = new ArrayList<Integer>();
        for (int i = 0; i < size; i++) {
            al.add(sal.get());
        }

        return al;

    }

    public static void main(String[] args) {
        Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                return new Random().nextInt(51) + 30;
            }
        };
        ArrayList<Integer> v = getter(5, supplier);
        System.out.println(v);
        ArrayList<Integer> v2 = getter(10, () -> new Random().nextInt(51) + 30);
        System.out.println(v2);
    }
}

函数型接口Function

构造

public interface Function<T,R>
表示接受一个参数并产生结果的函数。

方法

R apply(T t) 
将此函数应用于给定的参数。 
package top.zunmx.d3;

import java.awt.PrintGraphics;
import java.util.function.Function;

// ALC-Master
public class Test {
    public static int getNum(int num, Function<Integer, Integer> fun) {
        return fun.apply(num);

    }

    public static void main(String[] args) {
        Function<Integer, Integer> fun = new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer t) {
                return 2 * t;
            }
        };
        System.out.println(getNum(5, fun));

        Function<Integer, Integer> fun2 = (x) -> {
            return x * x;
        };
        System.out.println(getNum(5, fun2));
        System.out.println(getNum(5, x -> x * x * x));
    }
}

断言型接口Predicate

接受一个数据,并做出判断得到一个boolean类型的结果

方法

boolean test(T t) 
在给定的参数上评估这个谓词。  

实例

package top.zunmx.d4;

import java.security.AllPermission;
import java.util.ArrayList;
import java.util.function.Predicate;

// ALC-Master
public class Demo {
    public static void main(String[] args) {
        ArrayList<Integer> al = new ArrayList<Integer>();
        al.add(1);
        al.add(2);
        al.add(3);
        al.add(4);
        al.add(5);
        al.add(6);
        Predicate<Integer> pre = new Predicate<Integer>() {
            @Override
            public boolean test(Integer t) {
                return t % 2 == 0;
            }
        };
        ArrayList<Integer> rstAL = getArrayList(al, pre);
        System.out.println(rstAL);
        // Lambda
        System.out.println(getArrayList(al, (t) -> t % 2 != 0));
    }

    /*
     * 返回值类型:集合 ArrayList<Integer> 参数列表:ArrayList<Integer> al ,Predicate<Integer>
     * pre
     * 
     */
    public static ArrayList<Integer> getArrayList(ArrayList<Integer> al, Predicate<Integer> pre) {
        // 1. 创建集合,用来存储筛选之后的数据
        ArrayList<Integer> list = new ArrayList<Integer>();
        // 2. 遍历传入的集合
        for (Integer i : al) {
            /*
             * 3. 判断集合中的每个元素是奇数还是偶数
             * 
             * 判断就的操作是在test方法中进行,但是还没有重写,重写后就有了 将Predicate 对象传递过来的时候就重写好了
             */
            if (pre.test(i)) {
                list.add(i);
            }
        }
        return list;
    }
}

方法的引用

之前学习的函数式接口当作一个事情的解决方案来使用的(并且这个解决方案是以参数传递到方法中的),既然是一个解决方案了,但是Java中已经有了相同或类似的解决方案,那么我们就可以不用写了,而是直接使用Java官方提供好的解决方案就可以了(当作参数传递)。这种使用Java官方提供好的解决方案的行为被称为方法的引用。

方法引用的符号:

::

使用普通的方法

对象名::方法名

使用静态的方法

类名::方法名

实例

package top.zunmx.d5;

import java.util.function.Consumer;

// ALC-Master
public class Demo {
    public static void main(String[] args) {

        // 函数式接口+Lambda方式
        String str = "Hello";
        Consumer<String> con = (x) -> {
            System.out.println(x);
        };
        waste(str, con);

        // 方法引用
        waste(str, System.out::println);

    }

    public static void waste(String s, Consumer<String> con) {
        con.accept(s);
    }
}
package top.zunmx.d5;

import java.util.function.Supplier;

// ALC-Master
public class Demo2 {
    public static void main(String[] args) {
        // 函数式接口 + Lambda
        Supplier<Double> sup = () -> Math.random();
        System.out.println(getRandom(sup));

        // 方法引用的方式
        System.out.println(getRandom(Math::random));
    }

    // 此处函数式接口 Supplier 的作用为提供一个数
    public static double getRandom(Supplier<Double> sup) {
        return sup.get();

    }
}

什么时候使用方法引用

  1. 方法引用是为了简化冗余的Lambda表达式代码
  2. 如果函数式接口和Lambda中已经有定义好的了,就可以使用定义好的解决方案,就不用函数式接口和Lambda表达式再去自己重新写了。这样既简化了代码,也提升了代码的美观性。

StreamAPI

在JDK8之后出来,用来简化对集合的操作

获取Stream对象

  1. 单列集合获取Stream对象
   stream();
   ```

2. 双列集合获取Stream对象

```java
   keySet().stream();
   values().stream();
   entrySet().stream();
   ```

3. 数组获取Stream对象

Stream.of(T t);
```

```java
package top.zunmx.d6;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.stream.Stream;

// ALC-Master
public class Demo {
private void mian() {
ArrayList al = new ArrayList();
Stream alStream = al.stream();
HashMap hm = new HashMap();
Stream hmkStream = hm.keySet().stream();
Stream hmvStream = hm.values().stream();
Stream<Entry> hmeStream = hm.entrySet().stream();

    int[] arr = new int[3];
    Stream<int[]> arrStream = Stream.of(arr);
}

}

```

## 常见方法

java long count() ; //返回此流中的元素数。 void forEach(Consumer<? super T> action) ; //对此流的每个元素执行操作。 Stream<T> filter(Predicate<? super T> predicate) ; //返回由与此给定谓词匹配的此流的元素组成的流。 Stream<T> limit(long maxSize) ; //返回由此流的元素组成的流,截短长度不能超过 maxSize 。 Stream<T> skip(long n) ; //在丢弃流的第一个 n元素后,返回由该流的 n元素组成的流。

```java
package top.zunmx.d6;

import java.util.ArrayList;
import java.util.stream.Stream;

import javax.security.auth.x500.X500Principal;

// ALC-Master
public class Demo2 {
public static void main(String[] args) {
ArrayList al = new ArrayList();
al.add("杨过");
al.add("杨光");
al.add("张晓光");
al.add("小龙女");
al.add("施立旋");
al.add("杨癫疯");
// start
Stream stream = al.stream();
System.out.println(stream.count());
// end
System.out.println();
// start
stream = al.stream();
stream.forEach(System.out::println);
// or
al.forEach(System.out::println);
// end
System.out.println();
// start
stream = al.stream();
stream.filter(x -> x.charAt(0) == '杨').forEach(System.out::println);
// end
System.out.println();
// start
stream = al.stream();
stream.limit(3).forEach(System.out::println);
// end
System.out.println();
// start
stream = al.stream();
stream.skip(2).forEach(System.out::println);
// end
}

}

```

评论 0

还没有评论,来说点什么吧。

提交后需要审核才会公开。