java基础-8 函数式编程

函数式接口

 

  • 函数式接口概述

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

public class Test {
    public static void main(String[] args) {
        //匿名内部类
        startThread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "线程启动了!");
            }
        });
        //lambda表达式
        startThread(() ->System.out.println(Thread.currentThread().getName() + "线程启动了!"));

    }

    public static void startThread(Runnable rne) {
        new Thread(rne, "线程1").start();
    }
}
  • 函数式接口作为方法的返回值

public class Test {
    public static void main(String[] args) {
        //函数式接口作为方法的返回值
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("bbb");
        arrayList.add("c");
        arrayList.add("aa");
        arrayList.add("dddd");

        System.out.println("排序前: " + arrayList);
        //sort排序
        //Collections.sort(arrayList);  //排序后: [aa, bbb, c, dddd]
        //自定义比较器(按长度排序)
        Collections.sort(arrayList, getComparator());
        System.out.println("排序后: " + arrayList);
    }

    public static Comparator<String> getComparator(){
        //匿名内部类的方式实现
/*        return  new Comparator<String>(){
            @Override
            public int compare(String str1, String str2) {
                return str1.length() - str2.length();
            }
        };
*/
        //lambada表达式的方式实现
        return (str1, str2)->str1.length() - str2.length();
    }
}
  • 常用函数式接口

Supplier

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

 常用方法只有一个无参的方法

方法名

说明

T get()

按照某种实现逻辑(Lambda表达式实现)返回一个数据

public class Test {
    public static void main(String[] args) {
        //Supplier生产数据接口
        String str = getString(()->"李茂贞");
        System.out.println(str);

        Integer num = getInteger(()-> 25);
        System.out.println(num);

    }

    //定义一个方法返回一个字符串
    public static String getString(Supplier<String> supp){
        return supp.get();
    }

    //定义一个方法返回一个数字
    public static Integer getInteger(Supplier<Integer> supp){
        return supp.get();
    }
}

public class Test {
    public static void main(String[] args) {
        //Supplier生产数据接口
        int[] arr = {1, 5, 8, 3, 6, 9};
        int num = getMax(() -> {
            int max = arr[0];
            for (int i : arr) {
                if (i > max) {
                    max = i;
                }
            }
            return max;
        });
        System.out.println(num);

    }

    //定义一个方法返回一个字符串
    public static int getMax(Supplier<Integer> supp) {
        return supp.get();
    }
}
  • 常用函数式接口之Consumer

Consumer接口也被称为消费型接口,它消费的数据的数据类型由泛型指定  常用方法

Consumer:包含两个方法

方法名

说明

void accept(T t)

对给定的参数执行此操作

default Consumer andThen(Consumer after)

返回一个组合的Consumer,依次执行此操作,然后执行 after操作

 

public class Test {
    public static void main(String[] args) throws IOException {
        /*Consumer<T>:包含两个方法
        void accept​(T t):对给定的参数执行此操作
        default Consumer<T> andThen​(Consumer after):返回一个组合的 Consumer,依次执行此操作,然后执行 after操作
        Consumer<T>接口也被称为消费型接口,它消费的数据的数据类型由泛型指定*/

        //消费一个字符串,反转该字符串
/*        operatorString("李茂贞", (s) -> {
            System.out.println(new StringBuilder(s).reverse().toString());
        });*/
        //匿名内部类
        operatorString("往后余生", new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(new StringBuilder(s).reverse().toString());
            }
        }, new Consumer<String>() {
            @Override
            public void accept(String s) {
                String subStr = s.substring(0, 2);
                System.out.println(subStr);
                System.out.println(subStr.length());
            }
        });
        System.out.println("---------------------");
        //lambda表达式
        operatorString("李茂贞", s -> System.out.println(new StringBuilder(s).reverse().toString()));
        System.out.println("---------------------");
        //消费一个字符串,反转该字符串,切割字符串
        operatorString("往后余生", s -> System.out.println(new StringBuilder(s).reverse().toString()),
                s -> {
                    String subStr = s.substring(0, 2);
                    System.out.println(subStr);
                    System.out.println(subStr.length());
                });
    }

    //定义一个方法,消费一个字符串两次
    private static void operatorString(String name, Consumer<String> con, Consumer<String> con2) {
/*        con.accept(name);
        con2.accept(name);*/
        con.andThen(con2).accept(name);
/*        default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
        * */
    }

    //定义一个方法消费一个字符串
    private static void operatorString(String name, Consumer<String> con) {
        con.accept(name);
    }
}


/*
生余后往
往后
2
---------------------
贞茂李
---------------------
生余后往
往后
2
*/

public class ClientTcp {
    public static void main(String[] args) throws IOException {
        /*
    String[] strArray = {"李茂贞,25", "李淳风,27", "袁天罡,29"};
    字符串数组中有多条信息,请按照格式:"姓名:XX,年龄:XX"的格式将信息打印出来
    要求:
        把打印姓名的动作作为第一个Consumer接口的Lambda实例
        把打印年龄的动作作为第二个Consumer接口的Lambda实例
        将两个Consumer接口按照顺序组合到一起使用
 */
        String[] strArray = {"李茂贞,25", "李淳风,27", "袁天罡,29"};
        //匿名内部类的方式
/*        printInfo(strArray, new Consumer<String>() {
            @Override
            public void accept(String s) {
                String name = s.split(",")[0];
                System.out.print("姓名: " + name);
            }
        }, new Consumer<String>() {
            @Override
            public void accept(String s) {
                String age = s.split(",")[1];
                System.out.println(", 年龄:" + age);
            }
        });*/
        //lambda表达式的方式
/*        printInfo(strArray, (s) ->{
            String name = s.split(",")[0];
            System.out.print("姓名: " + name);
        }, (s)->{
            String age = s.split(",")[1];
            System.out.println(", 年龄: " + age);
        });*/
        //lambda表达式的省略模式
        printInfo(strArray, s -> System.out.print("姓名: " + s.split(",")[0]),
                s -> System.out.println(", 年龄: " + s.split(",")[1]));
    }

    //定义一个方法消费字符串数组
    private static void printInfo(String[] strArray, Consumer<String> con, Consumer<String> con2) {
        for (String str : strArray) {
            con.andThen(con2).accept(str);
        }
    }
}

/*
姓名: 李茂贞, 年龄: 25
姓名: 李淳风, 年龄: 27
姓名: 袁天罡, 年龄: 29
*/
  • 常用函数式接口之Predicate

Predicate接口通常用于判断参数是否满足指定的条件  常用方法

方法名

说明

boolean test(T t)

对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值

default Predicate negate()

返回一个逻辑的否定,对应逻辑非

default Predicate and(Predicate other)

返回一个组合判断,对应短路与

default Predicate or(Predicate other)

返回一个组合判断,对应短路或

/*
    Predicate<T>:常用的四个方法
        boolean test​(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
        default Predicate<T> negate​():返回一个逻辑的否定,对应逻辑非
        Predicate<T>接口通常用于判断参数是否满足指定的条件
 */
public class Test {
    public static void main(String[] args) {
        //匿名内部类
        boolean result = checkLength("往后余生", new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.length() > 5;
            }
        });
        System.out.println(result);
        //lambda表达式
        boolean checkResult = checkLength("余生,请多指教", s -> s.length() > 5);
        System.out.println(checkResult);
    }

    public static boolean checkLength(String str, Predicate<String> per) {
        //return per.test(str);
        return per.negate().test(str);  //negate 逻辑非
/*        default Predicate<T> negate() {
            return (t) -> !test(t);
        }*/
    }
}
/*
    Predicate<T>:
        default Predicate<T> and​(Predicate other):返回一个组合判断,对应短路与
        default Predicate<T> or​(Predicate other):返回一个组合判断,对应短路或
 */
public class Test {
    public static void main(String[] args) {
        //lambda表达式
        boolean checkResult = checkLength("余生,请多指教", s -> s.length() > 5 , s -> s.length() < 10);
        System.out.println(checkResult);

    }

    public static boolean checkLength(String str, Predicate<String> per1, Predicate<String> per2) {
/*        boolean re1 = per1.test(str);
        boolean re2 = per2.test(str);
        return re1 && re2;*/
        //等价于
        //return per1.and(per2).test(str);  //短路逻辑与
        /*        boolean re1 = per1.test(str);
        boolean re2 = per2.test(str);
        return re1 || re2;*/
        //等价于
        return per1.or(per2).test(str);  //短路逻辑或
    }
}

/*
    String[] strArray = {"李茂贞,25", "卫庄,27", "盖聂,30", "李淳风,31", "袁天罡,33"};
    字符串数组中有多条信息,请通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中,并遍历ArrayList集合
    要求:同时满足如下要求
        1:姓名长度大于2
        2:年龄小于31
    分析:
        1:有两个判断条件,所以需要使用两个Predicate接口,对条件进行判断
        2:必须同时满足两个条件,所以可以使用and方法连接两个判断条件
 */
public class Test {
    public static void main(String[] args) {
        String[] strArray = {"李茂贞,25", "卫庄,27", "盖聂,30", "李淳风,31", "袁天罡,33"};
        //lambda表达式
        ArrayList strList = checkLength(strArray, s -> s.split(",")[0].length() > 2 ,
                s -> Integer.parseInt(s.split(",")[1]) < 31);
        System.out.println(strList);
    }

    public static ArrayList<String> checkLength(String[] strArray, Predicate<String> per1, Predicate<String> per2) {
        ArrayList<String> strList = new ArrayList<>();
        for (String str: strArray){
            if (per1.and(per2).test(str)){
                strList.add(str);
            }
        }
        return strList;
    }
}

/*
[李茂贞,25]
*/
  • 常用函数式接口之Function

/*
    Function<T,R>:常用的两个方法
        R apply​(T t):将此函数应用于给定的参数
        default <V> Function andThen​(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
        Function<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值
 */
public class Test {
    public static void main(String[] args) {
        //匿名内部类
        convert("1252", new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.parseInt(s);
            }
        });
        //lambda表达式
        convert("125220", s -> Integer.parseInt(s));
        //引用类方法
        convert("125220", Integer::parseInt);
        System.out.println("---------------------------");
        convert(100, s -> String.valueOf(s+566));
        System.out.println("---------------------------");
        convert("100", s -> Integer.parseInt(s), s -> String.valueOf(s+899));
    }

    //定义一个方法,把一个字符串转换int类型,在控制台输出
    private static void convert(String str, Function<String, Integer> f) {
        Integer result = f.apply(str);
        System.out.println(result);
    }
    //定义一个方法,把一个int类型的数据加上一个整数之后,转为字符串在控制台输出
    private static void convert(int num, Function<Integer, String> f){
        String str = f.apply(num);
        System.out.println(str);
    }
    //定义一个方法,把一个字符串转换int类型,把int类型的数据加上一个整数之后,转为字符串在控制台输出
    public static void convert(String str, Function<String, Integer> f1, Function<Integer, String> f2){
/*        int num = f1.apply(str);
        String result = f2.apply(num);
        System.out.println(result);*/
        String result = f1.andThen(f2).apply(str);
        System.out.println(result);
    }
}


/*
1252
125220
125220
---------------------------
666
---------------------------
999
*/

  • Stream流

/*
    需求:按照下面的要求完成集合的创建和遍历
        1:创建一个集合,存储多个字符串元素
        2:把集合中所有以"张"开头的元素存储到一个新的集合
        3:把"张"开头的集合中的长度为3的元素存储到一个新的集合
        4:遍历上一步得到的集合
 */
public class Test {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

/*        //把集合中所有以"张"开头的元素存储到一个新的集合
        ArrayList<String> zhangList = new ArrayList<>();
        for (String name : list) {
            if (name.startsWith("张")) {
                zhangList.add(name);
            }
        }

        //把"张"开头的集合中的长度为3的元素存储到一个新的集合
        ArrayList<String> lenList = new ArrayList<String>();

        for (String s : zhangList) {
            if (s.length() == 3) {
                lenList.add(s);
            }
        }
        System.out.println(lenList);
        //Stream流来改进
        list.stream().filter((String s) -> s.startsWith("张")).filter((String s) -> s.length() == 3).forEach((String s) -> System.out.println(s));
        */
        //省略模式
        list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
    }
}

/*
张曼玉
张无忌
*/

Stream流的思想

 

  •  Stream流的生成方式

/*
    Stream流的常见生成方式
        1:Collection体系的集合可以使用默认方法stream​()生成流
            default Stream<E> stream​()
        2:Map体系的集合间接的生成流
        3:数组可以通过Stream接口的静态方法of​(T... values)生成流
 */
public class Test {
    public static void main(String[] args) {
        //1:Collection体系的集合可以使用默认方法stream​()生成流
        List<String> list = new ArrayList<String>();
        Stream<String> listStream = list.stream();

        Set<Integer> set = new HashSet<Integer>();
        Stream<Integer> setStream = set.stream();

        //2:Map体系的集合间接的生成流
        HashMap<String, Integer> hashMap = new HashMap<>();
        Stream<String> keyStream = hashMap.keySet().stream();
        Stream<Integer> valueStream = hashMap.values().stream();
        Stream<Map.Entry<String, Integer>> entryStream = hashMap.entrySet().stream();

        //3:数组可以通过Stream接口的静态方法of​(T... values)生成流
        String[] strArray = {"aaa", "www", "ddd"};
        Stream<String> strArray1 = Stream.of(strArray);
        Stream<String> strArray2 = Stream.of("aaa", "www", "ddd");
        Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
    }
}
  • Stream流中间操作方法

概念中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。

 常见方法

方法名

说明

Stream filter(Predicate predicate)

用于对流中的数据进行过滤

Stream limit(long maxSize)

返回此流中的元素组成的流,截取前指定参数个数的数据

Stream skip(long n)

跳过指定参数个数的数据,返回由该流的剩余元素组成的流

static Stream concat(Stream a, Stream b)

合并ab两个流为一个流

Stream distinct()

返回由该流的不同元素(根据Object.equals(Object) )组

成的流

Stream sorted()

返回由此流的元素组成的流,根据自然顺序排序

Stream sorted(Comparator comparator)

返回由该流的元素组成的流,根据提供的Comparator进行排序

Stream map(Function mapper)

返回由给定函数应用于此流的元素的结果组成的流

IntStream mapToInt(ToIntFunction mapper)

返回一个IntStream其中包含将给定函数应用于此流的元素的结果

/*
    Stream<T> filter​(Predicate predicate):用于对流中的数据进行过滤
    Predicate接口中的方法	boolean test​(T t):对给定的参数进行判断,返回一个布尔值
 */
public class Test {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        //需求1:把list集合中以张开头的元素在控制台输出
        //匿名内部类的方式
        list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张");
            }
        }).forEach(System.out::println);
        System.out.println("------------------------");
        //lambda表达式
        list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
        System.out.println("------------------------");
        //需求2:把list集合中长度为3的元素在控制台输出
        list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
        System.out.println("------------------------");
        //需求3:把list集合中以张开头的,长度为3的元素在控制台输出
        list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
    }
}

/*
张曼玉
张敏
张无忌
------------------------
张曼玉
张敏
张无忌
------------------------
林青霞
张曼玉
王祖贤
张无忌
------------------------
张曼玉
张无忌
*/

Stream limit(long maxSize)

返回此流中的元素组成的流,截取前指定参数个数的数据

Stream skip(long n)

跳过指定参数个数的数据,返回由该流的剩余元素组成的流

/*
    Stream<T> limit​(long maxSize):返回此流中的元素组成的流,截取前指定参数个数的数据
    Stream<T> skip​(long n):跳过指定参数个数的数据,返回由该流的剩余元素组成的流
 */
public class Test {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        //需求1:取前3个数据在控制台输出
        list.stream().limit(3).forEach(s -> System.out.println(s));
        System.out.println("-------------------");

        //需求2:跳过3个元素,把剩下的元素在控制台输出
        list.stream().skip(3).forEach(s -> System.out.println(s));
        System.out.println("-------------------");
        //需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
        list.stream().skip(2).limit(2).forEach(s -> System.out.println(s));
    }
}

/*
林青霞
张曼玉
王祖贤
-------------------
柳岩
张敏
张无忌
-------------------
王祖贤
柳岩
*/

static Stream concat(Stream a, Stream b)

合并ab两个流为一个流

Stream distinct()

返回由该流的不同元素(根据Object.equals(Object) )组

成的流

/*
    static <T> Stream<T> concat​(Stream a, Stream b):合并a和b两个流为一个流
    Stream<T> distinct​():返回由该流的不同元素(根据Object.equals(Object) )组成的流
 */
public class Test {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        ///需求1:取前4个数据组成一个流
        Stream<String> stream1 = list.stream().limit(4);

        //需求2:跳过2个数据组成一个流
        Stream<String> stream2 = list.stream().skip(2);

        //需求3:合并需求1和需求2得到的流
        Stream<String> concatStream = Stream.concat(stream1, stream2);

        //需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
        concatStream.distinct().forEach(System.out::println);
    }
}

/*
林青霞
张曼玉
王祖贤
柳岩
张敏
张无忌
*/

Stream sorted()

返回由此流的元素组成的流,根据自然顺序排序

Stream sorted(Comparator comparator)

返回由该流的元素组成的流,根据提供的Comparator进行排序

/*
    Stream<T> sorted​():返回由此流的元素组成的流,根据自然顺序排序
    Stream<T> sorted​(Comparator comparator):返回由该流的元素组成的流,根据提供的Comparator进行排序
        Comparator接口中的方法	int compare​(T o1, T o2)
 */
public class Test {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("linqingxia");
        list.add("zhangmanyu");
        list.add("wangzuxian");
        list.add("liuyan");
        list.add("zhangmin");
        list.add("zhangwuji");

        //需求1:按照自然顺序把数据在控制台输出
        list.stream().sorted().forEach(s -> System.out.println(s));
        System.out.println("--------------------");
        //需求2:按照字符串长度从大到小,字母从小到达顺序排序后把数据在控制台输出
        //匿名内部类的方式
        /*list.stream().sorted(new Comparator<String>() {
            @Override
            public int compare(String str1, String str2) {
                int num = str2.length() - str1.length();
                int result = num == 0? str1.compareTo(str2): num;
                return result;
            }
        }).forEach(s -> System.out.println(s));*/
        //lambda表达式
        list.stream().sorted((str1, str2)->{
            int num = str2.length() - str1.length();
            int result = num == 0? str1.compareTo(str2): num;
            return result;
        });
    }
}

/*
linqingxia
liuyan
wangzuxian
zhangmanyu
zhangmin
zhangwuji
--------------------
linqingxia
wangzuxian
zhangmanyu
zhangwuji
zhangmin
liuyan
*/

Stream map(Function mapper)

返回由给定函数应用于此流的元素的结果组成的流

IntStream mapToInt(ToIntFunction mapper)

返回一个IntStream其中包含将给定函数应用于此流的元素的结果

/*
    <R> Stream<R> map​(Function mapper):返回由给定函数应用于此流的元素的结果组成的流
        Function接口中的方法		R apply​(T t)
    IntStream mapToInt​(ToIntFunction mapper):返回一个IntStream其中包含将给定函数应用于此流的元素的结果
        IntStream:表示原始 int 流
        ToIntFunction接口中的方法	 int applyAsInt​(T value)
 */
public class Test {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("10");
        list.add("20");
        list.add("30");
        list.add("40");
        list.add("50");

        //需求:将集合中的字符串数据转换为整数之后在控制台输出
/*        list.stream().map(new Function<String, Object>() {
            @Override
            public Object apply(String s) {
                return Integer.parseInt(s);
            }
        });*/
        //list.stream().map((s) -> Integer.parseInt(s)).forEach(s -> System.out.println(s));
        //list.stream().map(Integer::parseInt).forEach(System.out::println);
        //map、和mapToInt的区别在于map返回一个Stream流,mapInt返回一个IntStream
        Stream<Integer> stream = list.stream().map(Integer::parseInt);
        IntStream intStream = list.stream().mapToInt(Integer::parseInt);

        //int sum​() 返回此流中元素的总和
        int result = intStream.sum();
        System.out.println(result);
    }
}

/*
150
*/
  • Stream流终结操作方法

概念

终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作。

 常见方法

方法名

说明

void forEach(Consumer action)

对此流的每个元素执行操作

long count()

返回此流中的元素数

public class Test {
    public static void main(String[] args) {
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("10");
        list.add("20");
        list.add("30");
        list.add("40");
        list.add("50");

        //long count()	返回此流中的元素数
        long count = list.stream().count();
        System.out.println(count);
    }
}
/*
5
*/

/*
    现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作:
        1:男演员只要名字为3个字的前三人
        2:女演员只要姓林的,并且不要第一个
        3:把过滤后的男演员姓名和女演员姓名合并到一起
        4:把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
            演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法
*/
public class Test {
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> manList = new ArrayList<String>();
        manList.add("周润发");
        manList.add("成龙");
        manList.add("刘德华");
        manList.add("吴京");
        manList.add("周星驰");
        manList.add("李连杰");

        ArrayList<String> womanList = new ArrayList<String>();
        womanList.add("林心如");
        womanList.add("张曼玉");
        womanList.add("林青霞");
        womanList.add("柳岩");
        womanList.add("林志玲");
        womanList.add("王祖贤");

/*        //男演员只要名字为3个字的前三人
        Stream<String> manStream = manList.stream().filter(s -> s.length() == 3);
        //女演员只要姓林的,并且不要第一个
        Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);
        //把过滤后的男演员姓名和女演员姓名合并到一起
        Stream<String> conStream = Stream.concat(manStream, womanStream);
        //把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
        conStream.map(s -> new Actor(s)).forEach(s -> System.out.println(s.getName()));*/

        //省略模式
        Stream.concat(manList.stream().filter(s -> s.length() == 3), womanList.stream().filter(s -> s.startsWith("林")).skip(1))
                .map(Actor::new).forEach(s -> System.out.println(s.getName()));
    }
}
/*
周润发
刘德华
周星驰
李连杰
林青霞
林志玲
*/
  • Stream流的收集操作

概念

对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中。

 常用方法

方法名

说明

R collect(Collector collector)

把结果收集到集合中

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

方法名

说明

public static Collector toList()

把元素收集到List集合中

public static Collector toSet()

把元素收集到Set集合中

public static Collector toMap(Function keyMapper,Function valueMapper)

把元素收集到Map集合中

/*
    Stream流的收集方法
        R collect​(Collector collector)

    它是通过工具类Collectors提供了具体的收集方式
        public static <T> Collector toList​():把元素收集到List集合中
        public static <T> Collector toSet​():把元素收集到Set集合中
        public static Collector toMap​(Function keyMapper,Function valueMapper):把元素收集到Map集合中
 */
public class Test {
    public static void main(String[] args) {
        //创建List集合对象
        List<String> list = new ArrayList<String>();
        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");

        //需求1:得到名字为3个字的流
        Stream<String> lenStream = list.stream().filter(s -> s.length() ==3);
        //需求2:把使用Stream流操作完毕的数据收集到List集合中并遍历
        List<String> collectList = lenStream.collect(Collectors.toList());
        for(String name: collectList) System.out.println(name);
        System.out.println("----------------------");
        //创建Set集合对象
        Set<Integer> set = new HashSet<Integer>();
        set.add(10);
        set.add(20);
        set.add(30);
        set.add(33);
        set.add(35);

        //需求3:得到年龄大于25的流
        Stream<Integer> integerStream = set.stream().filter(s -> s > 25);
        //需求4:把使用Stream流操作完毕的数据收集到Set集合中并遍历
        Set<Integer> ageSet = integerStream.collect(Collectors.toSet());
        for(Integer age: ageSet) System.out.println(age);
        System.out.println("----------------------");

        //定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成
        String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33", "柳岩,25"};
        //需求5:得到字符串中年龄数据大于28的流
        Stream<String> stringStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);
        //需求6:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,年龄作值
        Map<String, Integer> mapCollect = stringStream.collect(Collectors.toMap((s -> s.split(",")[0]), (s -> Integer.parseInt(s.split(",")[1]))));
        for(String key: mapCollect.keySet()){
            System.out.println("姓名: " + key + ", 年龄: " + mapCollect.get(key));
        }

    }
}
/*
林青霞
张曼玉
王祖贤
----------------------
33
35
30
----------------------
姓名: 林青霞, 年龄: 30
姓名: 王祖贤, 年龄: 33
姓名: 张曼玉, 年龄: 35
*/

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章