Java常用的函数式接口及流的使用

简介

**函数式接口(Functional Interface)**就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

函数式接口可以被隐式转换为 lambda 表达式,常与流一起用于对集合的操作。

**流(Stream)**是一个来自数据源的元素队列,Stream不会存储元素,而是按需计算。

函数式接口(Functional Interface)

常用的函数式接口有Supplier、Consumer、Predicate、Function等。

  • Supplier< T > :是一个生产型接口,包含一个无参有返回值的方法 < T > get(),用来获取一个泛型参数指定类型的对象数据,生产一个数据。
public class Demo1 {
    public static void main(String[] args) {
        //第一种写法,直接实例化接口
        Supplier<String> supplier = () -> "abc";
        String result1 = supplier.get();
        System.out.println(result1);

        //第二种写法,作为方法的参数动态生产不同数据类型的数据
        String result2 = invoke(()->"test");
        Integer result3 = invoke(()->10);
        System.out.print(result2 + "\n" + result3);
    }

    private static <T> T invoke(Supplier<T> supplier){
        return supplier.get();
    }
}
  • Consumer< T >:是一个消费型的接口,包含一个有参无返回值的方法 void accept(T t),用于接收一个需要消费掉的指定泛型的数据。
    (1)另外包含有一个默认方法 Consumer< T > andThen(Consumer< ? super T > after),可以实现将多个消费数据的操作进行组合。
public class Demo2 {
    public static void main(String[] args) {
        //第一种写法,直接实例化接口
        String s1 = "123";
        Consumer<String> consumer = a->System.out.println(a);
        consumer.accept(s1);

        //第二种写法,作为方法的参数消费数据
        String s2 = "456";
        String s3 = "789";
        invoke1(s2,a->System.out.println(a));
        invoke1(s3,a->System.out.println(a));

        invoke2(s2,s-> System.out.println("1."+s), s-> System.out.println("2."+s));

    }

    private static void invoke1(String b, Consumer<String> con){
        con.accept(b);
    }

    private static void invoke2(String b, Consumer<String> con1, Consumer<String> con2){
        //con1消费完后con2再消费
        con1.andThen(con2).accept(b);
    }
}
  • Predicate< T >:是一个判断型接口,包含一个有参有返回值的方法 boolean test(T t),使用传入的数据进行判断操作。
    有三个默认方法:与、或、非三种逻辑判断的方法:
    (1)Predicate< T > and(Predicate< ? super T > other),与;
    (2)Predicate< T > or(Predicate< ? super T > other),或;
    (3)Predicate< T > negate(),非。.
public class Demo3 {
    public static void main(String[] args) {
        //第一种写法,直接实例化接口
        Predicate<String> pre1=(t)->t.equals("good");
        Predicate<String> pre2=(t)->t.endsWith("d");

        boolean result1 = pre1.test("good");
        System.out.println(result1);

        boolean result2 = pre1.negate().test("good");
        System.out.println(result2);

        boolean result3 = pre1.and(pre2).test("good");
        System.out.println(result3);

        boolean result4 = pre1.or(pre2).test("good");
        System.out.println(result4);
        
        System.out.println("-------------------------------");
        //第二种写法,作为方法的参数对传入的数据进行判断
        int m = 10;
        invoke1(m, n->n < 10);//false
        invoke2(m, n->n == 10, n->n < 10);//false
        invoke3(m, n->n == 10, n->n < 10);//true
        invoke4(m, n->n == 10, n->n < 10);//false
    }

    private static void invoke1(Integer n,Predicate<Integer> pre){
        boolean result1 = pre.test(n);
        System.out.println(result1);
    }

    private static void invoke2(Integer n,Predicate<Integer> pre1, Predicate<Integer> pre2){
        boolean result2 = pre1.and(pre2).test(n);
        System.out.println(result2);
    }

    private static void invoke3(Integer n,Predicate<Integer> pre1, Predicate<Integer> pre2){
        boolean result3 = pre1.or(pre2).test(n);
        System.out.println(result3);
    }

    private static void invoke4(Integer n,Predicate<Integer> pre1, Predicate<Integer> pre2){
        boolean result4 = pre1.negate().or(pre2).test(n);
        System.out.println(result4);
    }
}
  • Function< T , R >:由前一种数据类型的数据获得后一种数据类型的数据,包含有一个有参有返回值的方法 R apply(T t),根据 T 类型得到 R 类型。
    (1)包含一个默认方法 Function< T, R > andThen(Function<? super T> after),可以对多个Function接口进行组合操作。
public class Demo4 {
    public static void main(String[] args) {
        //第一种写法
        Function<String,Boolean> function = n->n.equals("one");
        Boolean result = function.apply("two");//false
        System.out.println(result);
        System.out.println("----------------------");

        //第二种写法
        String n = "one";
        invoke1(n, s->s.equals("one"));//true
        invoke2(n, s1->s1.equals("two"), s2->{
            if(s2){
                return "three";
            }else{
                return "two";
            }
        });//false->"two"
    }

    private static void invoke1(String s, Function<String, Boolean> function){
        Boolean result = function.apply(s);
        System.out.println(result);
    }

    private static void invoke2(String s, Function<String, Boolean> function1, Function<Boolean, String> function2){
        String result = function1.andThen(function2).apply(s);//先String->Boolean,再Boolean->String
        System.out.println(result);
    }
}

流(Stream)

一般与函数式接口配合用在对集合操作的简化上。

  • 获取流
    (1)所有Collection集合都可以通过默认方法 stream() 获取流;
ArrayList<String> list = new ArrayList<>();
Stream<String> stream = list.stream();

(2)Stream 接口的静态方法 of 可以获取数组或集合对应的流。static < T > Stream < T > of(T…value).

int[] str = new int[10];
ArrayList<String> list1 = new ArrayList<>();
Stream<int[]> str1 = Stream.of(str);
Stream<ArrayList<String>> stream1 = Stream.of(list1);
  • 流的常用方法
    (1)void forEach(Consumer<? super T> action):是一个终结方法,参数使用消费型接口。用于遍历。
    (2)long count():终结方法,计算流中元素的个数。
    (3)Stream< T > filter(Predicate<? super T > predicate):过滤,根据条件过滤流,参数使用Predicate函数式接口。
    (4)< R > Stream< R > map(Function<? super T, ? extends R> mapper):映射,将 T 类型数据转换成 R 类型数据。参数使用Function函数式接口。
    (5)Stream< T > limit(long maxSize):截取,截取前 maxSize 个元素组成新的流,若集合当前长度大于参数则进行截取,否则不进行操作。
    (6)Stream< T > skip(long n):跳过,跳过前 n 个,去剩余元素组成新的流,若流的长度大于 n,则跳过前 n 个,否则将会得到一个长度为 0 空流。
    (7)static < T > Stream< T > concat(Stream<? extends T> a, Stream<? extends T> b):将两个流组合成一个新的流。
public class Demo2 {
    public static void main(String[] args) {
        //Collection集合如ArrayList
        ArrayList<Integer> list = new ArrayList<>();
        list.add(0);
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);

        Stream<Integer> stream1 = list.stream();
        stream1.forEach(a->System.out.println(a));//遍历
        System.out.println("-------------------------");

        Stream<Integer> stream2 = list.stream();
        long count = stream2.count();//统计
        System.out.println("list集合的元素个数:"+count);
        System.out.println("-------------------------");

        Stream<Integer> stream8 = list.stream();
        stream8.filter(f->f==1).forEach(f-> System.out.println(f));//过滤,只保留1
        System.out.println("-------------------------");

        Stream<Integer> stream3 = list.stream();
        stream3.map(b->b==4).forEach(b-> System.out.println(b));//映射
        System.out.println("-------------------------");

        Stream<Integer> stream4 = list.stream();
        stream4.limit(2).forEach(c-> System.out.println(c));//截取
        System.out.println("-------------------------");

        Stream<Integer> stream5 = list.stream();
        stream5.skip(2).forEach(d-> System.out.println(d));//跳过
        System.out.println("-------------------------");

        Stream<Integer> stream6 = list.stream();//第一个流
        HashSet<Integer> set = new HashSet<>();
        set.add(10);
        set.add(20);
        set.add(30);
        Stream<Integer> stream7 = set.stream();//第二个流
        Stream<Integer> concat = Stream.concat(stream6, stream7);//合并
        concat.forEach(e-> System.out.println(e));
        System.out.println("-------------------------");

        //Map集合获取流的方法
        HashMap<Integer,String> map = new HashMap<>();
        //1.获取键,存储到Set集合中
        Set<Integer> keySet = map.keySet();
        Stream<Integer> stream9 = keySet.stream();
        //2.获取值,存储到Collection集合中
        Collection<String> values = map.values();
        Stream<String> stream10 = values.stream();
        //3.获取键值对(键与值的映射关系 entrySet)
        Set<Map.Entry<Integer, String>> entries = map.entrySet();
        Stream<Map.Entry<Integer, String>> stream11 = entries.stream();
    }
}

一个流可同时使用多个非终结方法,可以极大简化代码的数量,但一个流只能使用一次,且调用终结方法后不能再调用其他流的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值