zoukankan      html  css  js  c++  java
  • Java笔记之 函数式接口、Stream流

    函数式接口

    函数式接口概述

    函数式接口:有且仅有一个抽象方法的接口

    Java的函数式编程体现就是Lambda表达式,所以函数式接口就是可以适用于Lambda使用的接口,只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利的进行推导。

    如何检测一个接口是不是函数式接口呢?

    @FunctionalInterface,放在接口定义的上方:如果接口是函数式接口,那么编译通过,如果不是,编译失败

    自己定义的时候,加不加上这个注解都可以,但是建议加上。

    函数式接口作为方法的参数

    需求:

    定义一个RunnableDemo类,在类中提供两个方法

    1.startThread(Runnable r),方法参数Runnable是一个函数式接口。

    2.主方法,在主方法中调用startThread方法。

    如果方法的参数是一个函数式接口,我们可以使用Lambda表达式作为参数传递

    startThread(()->System.out.println(Thread.currentThread().getName()+"线程启动了"));

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      public class RunnableDemo {
    4.  
      public static void main(String[] args) {
    5.  
      startThread(new Runnable() {
    6.  
      @Override
    7.  
      public void run() {
    8.  
      System.out.println(Thread.currentThread().getName()+"线程启动了");
    9.  
      }
    10.  
      });
    11.  
      }
    12.  
      startThread(()->System.out.println(Thread.currentThread().getName()+"线程启动了"));
    13.  
       
    14.  
      private static void startThread(Runnable r) {
    15.  
      // Thread t = new Thread(r);
    16.  
      // t.start();
    17.  
      new Thread(r).start();
    18.  
      }
    19.  
      }

    函数式接口作为方法的返回值

    需求:

    定义一个ComparatorDemo类,在类中提供两个方法

    1.Comparator<String> getComparator(),方法返回值Comparator是一个函数式接口。

    2.主方法,在主方法中调用getComparator()方法。

    如果方法返回是一个函数式接口,我们可以使用Lambda表达式作为结果返回

    private static Comparator<String> getComparator(){

        return (s1,s2)->s1.length()-s2.length();

    }

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      import java.util.ArrayList;
    4.  
      import java.util.Collections;
    5.  
      import java.util.Comparator;
    6.  
       
    7.  
      public class ComparatorDemo {
    8.  
      public static void main(String[] args) {
    9.  
      ArrayList<String> s = new ArrayList<>();
    10.  
      s.add("sss");
    11.  
      s.add("derde");
    12.  
      s.add("asedeff");
    13.  
      s.add("w");
    14.  
      System.out.println(s);
    15.  
      Collections.sort(s);
    16.  
      System.out.println(s);
    17.  
      Collections.sort(s,getComparator());
    18.  
      System.out.println(s);
    19.  
       
    20.  
      }
    21.  
      private static Comparator<String> getComparator(){
    22.  
      //匿名内部类的实现
    23.  
      // Comparator<String> comp = new Comparator<String>() {
    24.  
      // @Override
    25.  
      // public int compare(String s1, String s2) {
    26.  
      // return s1.length()-s2.length();
    27.  
      // }
    28.  
      // };
    29.  
      // return comp;
    30.  
       
    31.  
      // return new Comparator<String>() {
    32.  
      // @Override
    33.  
      // public int compare(String s1, String s2) {
    34.  
      // return s1.length()-s2.length();
    35.  
      // }
    36.  
      // };
    37.  
       
    38.  
      // return (String s1,String s2)->{
    39.  
      // return s1.length()-s2.length();
    40.  
      // };
    41.  
       
    42.  
      return (s1,s2)->s1.length()-s2.length();
    43.  
      }
    44.  
       
    45.  
      }

    常用的函数式接口

    1.Supplier接口

    2.Consumer接口

    3.Predicate接口

    4.Function接口

    Supplier接口

    Supplier<T> :包含一个无参的方法

    该方法不需要参数,他会按照某种实现逻辑(由Lambda表达式实现)返回一个数据。

    Supplier<T> 接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      import java.util.function.Supplier;
    4.  
       
    5.  
      public class SupplierDemo {
    6.  
      public static void main(String[] args) {
    7.  
      String s = getString(new Supplier<String>() {
    8.  
      @Override
    9.  
      public String get() {
    10.  
      return "zayn";
    11.  
      }
    12.  
      });
    13.  
      System.out.println(s);
    14.  
      String ss = getString(()-> "zayn");
    15.  
      System.out.println(ss);
    16.  
      int x = getInteger(()->22);
    17.  
      System.out.println(x);
    18.  
      }
    19.  
      private static String getString(Supplier<String> sup){
    20.  
      return sup.get();
    21.  
      }
    22.  
      public static Integer getInteger(Supplier<Integer> sup){
    23.  
      return sup.get();
    24.  
      }
    25.  
       
    26.  
      }

    Consumer接口

    Consumer<T>包含两个方法

    1.void accept(T t):对给定的参数执行此操作

    2.default Consumer<T> andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作

    Consumer<T>接口也被称为消费型接口,他消费的数据的数据类型由泛型指定

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      import java.util.function.Consumer;
    4.  
       
    5.  
      public class ConsumerDemo {
    6.  
      public static void main(String[] args) {
    7.  
      operateString("hh", new Consumer() {
    8.  
      @Override
    9.  
      public void accept(Object s) {
    10.  
      System.out.println(s);
    11.  
      }
    12.  
      });
    13.  
      operateString("zayn",(s)-> System.out.println(s));
    14.  
      operateString("naill",System.out::println);
    15.  
      operateString("zayn",(s)-> System.out.println(s),(s)-> System.out.println(new StringBuilder(String.valueOf(s)).reverse().toString()));
    16.  
      }
    17.  
      private static void operateString(String s,Consumer con){
    18.  
      con.accept(s);
    19.  
      }
    20.  
      private static void operateString(String s,Consumer con1,Consumer con2){
    21.  
      con1.andThen(con2).accept(s);
    22.  
       
    23.  
      }
    24.  
      }

    Predicate接口

    Predicate<T>:常用的四个方法

    1.boolean test(T t):对于给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值。

    2.default Predicate<T> negate():返回一个逻辑的否定,对应逻辑非

    3.default Predicate<T> and(Predicate other):返回一个组合判断,对应短路与

    4.default Predicate<T> or (Predicate other):返回一个组合判断,对应短路或

    Predicate<T> 接口通常用于判断参数是否满足指定条件

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      import java.util.function.Predicate;
    4.  
       
    5.  
      public class PredicateDemo {
    6.  
      public static void main(String[] args) {
    7.  
      //boolean b = checkString("zayn",s-> s.length()>5);
    8.  
      boolean b = checkString("zayn",(String s)->{
    9.  
      return s.length()>5;
    10.  
      });
    11.  
      System.out.println(b);
    12.  
      boolean bb = checkString("zayn",s->s.length()>5,s -> s.length()<10);
    13.  
      System.out.println(bb);
    14.  
       
    15.  
      }
    16.  
      private static boolean checkString(String s, Predicate<String> p){
    17.  
      //return p.test(s);
    18.  
      //return !p.test(s);
    19.  
      return p.negate().test(s);
    20.  
      }
    21.  
      private static boolean checkString(String s, Predicate<String> p1,Predicate<String> p2){
    22.  
      // boolean b1= p1.test(s);
    23.  
      // boolean b2= p2.test(s);
    24.  
      // return b1&&b2;
    25.  
      //return p1.and(p2).test(s);
    26.  
      return p1.or(p2).test(s);
    27.  
      }
    28.  
      }

     Function接口

    Function<T,R>:常用的两个方法

    1. R apply(T t):将此函数应用于给定的参数

    2.default<V> Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果

    Function<T,R>接口通常用于对参数进行处理、转换(处理逻辑由Lambda表达式实现),然后返回一个新的值

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      import java.util.function.Function;
    4.  
       
    5.  
      public class FunctionDemo {
    6.  
      public static void main(String[] args) {
    7.  
      convert("100",s->Integer.parseInt(s));
    8.  
      convert("100",Integer::parseInt);
    9.  
      convert(100,i->String.valueOf(i+566));
    10.  
      convert("100",s->Integer.parseInt(s),i->String.valueOf(i+566));
    11.  
      }
    12.  
      //定义一个方法,把一个字符串转换为int类型,在控制台上输出
    13.  
      private static void convert(String s, Function<String,Integer> fun){
    14.  
      int i = fun.apply(s);
    15.  
      System.out.println(i);
    16.  
      }
    17.  
      //定义一个方法,把一个int类型的数据加上一个整数后,转换为字符串进行输出
    18.  
      private static void convert(int i ,Function<Integer,String> fun){
    19.  
      String s = fun.apply(i);
    20.  
      System.out.println(s);
    21.  
      }
    22.  
      //定义一个方法,把一个字符串转换为int类型,把一个int类型的数据加上一个整数后,转换为字符串进行输出
    23.  
      private static void convert(String s,Function<String,Integer> fun1,Function<Integer,String> fun2){
    24.  
      // String ss = fun2.apply(fun1.apply(s));
    25.  
      // System.out.println(ss);
    26.  
      String ss = fun1.andThen(fun2).apply(s);
    27.  
      System.out.println(ss);
    28.  
      }
    29.  
       
    30.  
      }

    Stream流

    体验Stream流

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      import java.util.ArrayList;
    4.  
       
    5.  
      public class StreamDemo {
    6.  
      public static void main(String[] args) {
    7.  
      ArrayList<String> list = new ArrayList<>();
    8.  
      list.add("林青霞");
    9.  
      list.add("张曼玉");
    10.  
      list.add("王祖贤");
    11.  
      list.add("柳岩");
    12.  
      list.add("张三");
    13.  
      list.add("张无忌");
    14.  
      list.stream().filter(s->s.length()==3).filter(s -> s.startsWith("张")).forEach(System.out::println);
    15.  
      }
    16.  
      }

    Stream流的生成方式

    stream流的常见生成方式

    1.Collection体系的集合可以使用默认方法stream()生成流    default Stream<E> stream()

    2.Map体系的集合间接的生成流

    3.数组可以通过Stream接口的静态方法of(T...values)生成流

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      import java.util.*;
    4.  
      import java.util.stream.Stream;
    5.  
       
    6.  
      public class StreamDemo1 {
    7.  
      public static void main(String[] args) {
    8.  
       
    9.  
      //Collection体系的集合可以使用默认方法stream()生成流 default Stream<E> stream()
    10.  
      List<String> l = new ArrayList<>();
    11.  
      Stream<String> listStream = l.stream();
    12.  
      Set<String> s = new HashSet<>();
    13.  
      Stream<String> setStream = s.stream();
    14.  
       
    15.  
      //Map体系的集合间接的生成流
    16.  
      Map<String,Integer> map = new HashMap<>();
    17.  
      Stream<String> keyStream = map.keySet().stream();
    18.  
      Stream<Integer> valueStream = map.values().stream();
    19.  
      Stream<Map.Entry<String,Integer>> entryStream = map.entrySet().stream();
    20.  
       
    21.  
      //数组可以通过Stream接口的静态方法of(T...values)生成流
    22.  
      String[] strArray = {"hello","java","zayn"};
    23.  
      Stream<String> strArrayStream1 = Stream.of(strArray);
    24.  
      Stream<String> strArrayStream2 = Stream.of("hello","java","zayn");
    25.  
      Stream<Integer>intStream = Stream.of(1,2,3,4,5);
    26.  
      }
    27.  
      }

    Stream流中常见的中间操作方法

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      import java.util.ArrayList;
    4.  
      import java.util.stream.Stream;
    5.  
       
    6.  
      public class StreamDemo2 {
    7.  
      public static void main(String[] args) {
    8.  
      ArrayList<String> list = new ArrayList<>();
    9.  
      list.add("林青霞");
    10.  
      list.add("张曼玉");
    11.  
      list.add("王祖贤");
    12.  
      list.add("柳岩");
    13.  
      list.add("张敏");
    14.  
      list.add("张无忌");
    15.  
       
    16.  
      //需求1:取前3个数据在控制台输出
    17.  
      list.stream().limit(3).forEach(System.out::println);
    18.  
      System.out.println("--------");
    19.  
      //需求2:跳过前三个数据,剩余的数据在控制台输出
    20.  
      list.stream().skip(3).forEach(System.out::println);
    21.  
      System.out.println("--------");
    22.  
      //需求3:跳过前2个数据,取前2个数据在控制台输出
    23.  
      list.stream().skip(2).limit(2).forEach(System.out::println);
    24.  
      System.out.println("--------");
    25.  
      //需求4:取前4个数据组成一个流
    26.  
      Stream<String> s1 = list.stream().limit(4);
    27.  
      System.out.println("--------");
    28.  
      //需求5:跳过2个数据组成一个流
    29.  
      Stream<String> s2 = list.stream().skip(2);
    30.  
      System.out.println("--------");
    31.  
      //需求6:合并需求4和需求5得到一个流,并把结果在控制台上输出
    32.  
      //Stream.concat(s1,s2).forEach(System.out::println);
    33.  
      System.out.println("--------");
    34.  
      //需求7:合并需求4和需求5得到一个流,并把结果在控制台上输出,要求字符串元素不能重复
    35.  
      Stream.concat(s1,s2).distinct().forEach(System.out::println);
    36.  
      System.out.println("--------");
    37.  
      System.out.println("deretfrefewrfgerg");
    38.  
      }
    39.  
      }
    40.  
       
    41.  
      package com.FunctionInterface;
    42.  
       
    43.  
      import java.util.ArrayList;
    44.  
       
    45.  
      public class StreamDemo3 {
    46.  
      public static void main(String[] args) {
    47.  
      ArrayList<String> list = new ArrayList<>();
    48.  
      list.add("defrefrg");
    49.  
      list.add("deffffff");
    50.  
      list.add("cdfref");
    51.  
      list.add("aaa");
    52.  
      list.add("wwwwwwww");
    53.  
      list.add("defferrf");
    54.  
       
    55.  
      //需求1:按照字母顺序把数据在控制台输出
    56.  
      list.stream().sorted().forEach(System.out::println);
    57.  
      System.out.println("--------");
    58.  
      //需求2:按照字符串长度把数据在控制台输出
    59.  
      //list.stream().sorted((s1,s2)->s1.length()-s2.length()).forEach(System.out::println);
    60.  
      list.stream().sorted((s1,s2)->{
    61.  
      int l = s1.length()-s2.length();
    62.  
      int num = l==0?s1.compareTo(s2):l;
    63.  
      return num;
    64.  
      }).forEach(System.out::println);
    65.  
      //需求1:按照字母顺序把数据在控制台输出
    66.  
      }
    67.  
      }
    68.  
       
    69.  
       
    70.  
      package com.FunctionInterface;
    71.  
       
    72.  
      import java.util.ArrayList;
    73.  
       
    74.  
      public class StreamDemo4 {
    75.  
      public static void main(String[] args) {
    76.  
      ArrayList<String> list = new ArrayList<>();
    77.  
      list.add("10");
    78.  
      list.add("20");
    79.  
      list.add("30");
    80.  
      list.add("40");
    81.  
      list.add("50");
    82.  
       
    83.  
      //需求:将集合中的数据转换成整数后在控制台输出
    84.  
      //list.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);
    85.  
      list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
    86.  
       
    87.  
      //int sum() 返回此流中元素对总和
    88.  
      int result = list.stream().mapToInt(Integer::parseInt).sum();
    89.  
      System.out.println(result);
    90.  
      }
    91.  
      }
    92.  
       

    Stream流中常见的终结方法

    1.void forEach(Consumer action):对流的每个元素执行操作,Consumer接口中的方法 void accept(T t):对给定的参数执行此操作

    2.long count():返回此流的元素数

    1.  
      package com.FunctionInterface;
    2.  
       
    3.  
      import java.util.ArrayList;
    4.  
       
    5.  
      public class StreamDemo {
    6.  
      public static void main(String[] args) {
    7.  
      ArrayList<String> list = new ArrayList<>();
    8.  
      list.add("林青霞");
    9.  
      list.add("张曼玉");
    10.  
      list.add("王祖贤");
    11.  
      list.add("柳岩");
    12.  
      list.add("张三");
    13.  
      list.add("张无忌");
    14.  
      //list.stream().filter(s->s.length()==3).filter(s -> s.startsWith("张")).forEach(System.out::println);
    15.  
      list.stream().forEach(System.out::println);
    16.  
      System.out.println(list.stream().filter(s -> s.startsWith("张")).count());
    17.  
      }
    18.  
      }

    Stream流的收集操作

    对数据使用Stream流的方式操作完毕后,我想把流中的数据收集到集合中,怎么办?

    Stream流的收集方法

    1.R collect(Collector collector)

    2.但是这个收集方法的参数是一个collection的接口

    工具类Collectors提供了具体的收集方式

    1.public static <T> Collector toList():把元素收集到list集合中

    2.public static <T> Collector toSet():把元素收集到set集合中

    3.public static Collector toMap(Function keyMapper,Function valueMapper):把元素收集到map集合中

    1.  
      package com.FunctionInterface;
    2.  
      import java.util.*;
    3.  
      import java.util.stream.Collector;
    4.  
      import java.util.stream.Collectors;
    5.  
      import java.util.stream.Stream;
    6.  
       
    7.  
       
    8.  
      public class CollectionDemo1 {
    9.  
      public static void main(String[] args) {
    10.  
      List<String> list = new ArrayList<>();
    11.  
      list.add("林青霞");
    12.  
      list.add("张曼玉");
    13.  
      list.add("王祖贤");
    14.  
      list.add("柳岩");
    15.  
       
    16.  
      //需求1.得到名字为3个字的流
    17.  
      Stream<String> stream = list.stream().filter(s->s.length()==3);
    18.  
       
    19.  
      //需求2.把stream流操作完毕的数据收集到List集合中并遍历
    20.  
      //List<String> names = stream.collect(Collectors.toList());
    21.  
      Set<String> names = stream.collect(Collectors.toSet());
    22.  
      for(String name:names){
    23.  
      System.out.println(name);
    24.  
      }
    25.  
       
    26.  
      //创建set集合
    27.  
      Set<Integer> set = new HashSet<>();
    28.  
      set.add(10);
    29.  
      set.add(20);
    30.  
      set.add(30);
    31.  
      set.add(40);
    32.  
      set.add(50);
    33.  
       
    34.  
      //需求3.得到年龄大于25的流
    35.  
      Stream<Integer> stream1 = set.stream().filter(i->i>25);
    36.  
       
    37.  
      //需求4.把stream流操作完毕的数据收集到Set集合中并遍历
    38.  
      Set<Integer> s = stream1.collect(Collectors.toSet());
    39.  
      for(int i : s){
    40.  
      System.out.println(i);
    41.  
      }
    42.  
       
    43.  
      //定义一个字符串数组,每一个字符串的数据由姓名和年龄组成
    44.  
      String[] strArray = { "林青霞,30","张曼玉,35","王祖贤,33","柳岩,25"};
    45.  
       
    46.  
      //需求5.得到字符串中年龄大于28的流
    47.  
      Stream<String> stream2 = Stream.of(strArray).filter( ss ->Integer.parseInt(ss.split(",")[1])>28);
    48.  
       
    49.  
      //需求6.把stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名做键,年龄做值
    50.  
      Map<String,Integer> map = stream2.collect(Collectors.toMap(s1->s1.split(",")[0],s2->Integer.parseInt(s2.split(",")[1])));
    51.  
      Set<String> keySet = map.keySet();
    52.  
      for(String key :keySet){
    53.  
      System.out.println(key+":"+map.get(key));
    54.  
      }
    55.  
      }
    56.  
      }
  • 相关阅读:
    @ControllerAdvice + @ExceptionHandler 使用
    将博客搬至CSDN
    Docker pull网络错误
    Centos7.5安装Docker
    Oracle18c创建不带C##的用户
    Centos7.5静默安装Oracle18c
    nodeJs和JavaScript的异同
    maven项目引入本地包,不使用中央仓库
    java中把指数形式的数字转为正常形式显示
    validateJarFile jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
  • 原文地址:https://www.cnblogs.com/coder-ahao/p/14224026.html
Copyright © 2011-2022 走看看