JAVA8 - 流 & 方法引用

流的使用

Stream 操作的三个步骤:

  • 创建Stream
    一个数据源(如:集合、数组),获取一个流
  • 中间操作
    一个中间操作链,对数据源的数据进行处理
  • 终止操作(终端操作)
    一个终端操作,执行中间操作链,并产生结果

创建 Stream 对象

package com.day01;

import org.junit.Test;

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


package com.study.map.immutable;

import java.util.*;
import java.util.stream.Stream;

public class Demo2 {
    public static void main(String[] args) {
        //单列集合获取流
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "1", "2", "3");

        list.stream().forEach(s -> System.out.println(s));


        //双列集合
        HashMap<String, Integer> map = new HashMap<>();
        map.put("aaa", 111);
        map.put("bbb", 222);
        map.put("ccc", 333);
        map.put("ddd", 444);

        map.keySet().stream().forEach(s -> System.out.println(s)); //输出map的每个键
        /*
        aaa
        ccc
        bbb
        ddd
         */
        map.entrySet().stream().forEach(s -> System.out.println(s));
        /*
        aaa=111
        ccc=333
        bbb=222
        ddd=444
         */


        //数组
        int[] arrr = {1,2,3,4,5};
        Arrays.stream(arrr).forEach(s -> System.out.println(s));

        /*
        1
        2
        3
        4
        5
         */

        //通过Stream 类中的静态方法of()
        Stream<String> stream3 = Stream.of("a", "b", "c");
        stream3.forEach(s -> System.out.println(s));
    }
}

中间方法

注意细节:

  • 中间方法,返回的Steam流,一旦操作过终结操作,就不能再次使用,建议使用链式编程
  • 修改Stream流中的数据,不会影响原来集合或数组中的数据
package com.study.streamdemo;

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

public class StreamDemo1 {

    public static void main(String[] args) {

        ArrayList<String> list = new ArrayList<>();

        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张蹒跚");

        Stream<String> sream1 = list.stream().filter(s -> s.startsWith("张"));
        sream1.forEach(s-> System.out.println(s));  //forEach 之后该流不能再使用

       //  Stream<String> stream2 = sream1.filter(s -> s.length() == 3);  sream1 再次使用 会抛Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or close

        //map 使用方法:类型转换
        ArrayList<String> list2 = new ArrayList<>();

        Collections.addAll(list2,"李四-25","小明-32");
        list2.stream().map(s->Integer.parseInt(s.split("-")[1])).forEach(s-> System.out.print(s)); //253212345678


        //合并流
        ArrayList<Integer> list3 = new ArrayList<>();
        Collections.addAll(list3,1,2,3,4);

        ArrayList<Integer> list4 = new ArrayList<>();
        Collections.addAll(list4,5,6,7,8);

        Stream.concat(list3.stream(),list4.stream()).forEach(s-> System.out.print(s)); //12345678

        System.out.println("--------------------------------------------------");

        //distanct 去重, 依赖equals 和 hashcode 方法
        ArrayList<String> list5 = new ArrayList<>();
        Collections.addAll(list5,"5","5","6","6");

        list5.stream().distinct().forEach(s-> System.out.print(s)); //56

    }
}

Stream 流的终结方法

package com.study.streamdemo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;

public class StreamDemo2 {

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张蹒跚");

        //count();
        System.out.println(list.stream().count());  //5

        //toArray() - 匿名内部类写法
/*        String[] strings = list.stream().toArray(new IntFunction<String[]>() {
            @Override
            public String[] apply(int value) {  //value 代表list的长度
                return new String[value];
            }
        });
        System.out.println(Arrays.toString(strings));*/   //[张无忌, 周芷若, 赵敏, 张强, 张蹒跚]

        //toArray() - lambda 写法
        String[] strings = list.stream().toArray(value -> new String[value]);
        System.out.println(Arrays.toString(strings));   //[张无忌, 周芷若, 赵敏, 张强, 张蹒跚]
    }
}

collect() 收集方法

package com.study.streamdemo;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;

public class StreanDemo3 {

    public static void main(String[] args) {

        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌-男-18", "周芷若-女-20", "赵敏-女-20", "张强-男-21", "张蹒跚-男-21");

        //过滤数据后转换为ArrayList
        List<String> list2 = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toList());
        System.out.println(list2); //[张无忌-男-18, 张强-男-21, 张蹒跚-男-21]


        //过滤数据后转换为Hashset
        Set<String> set = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toSet());
        System.out.println(set);  //[张蹒跚-男-21, 张强-男-21, 张无忌-男-18]


        //转换为HashMap - 匿名内部类写法
        /*
        toMap参数介绍:
            - 第一个参数函数式接口Function<String, String>:
                * 第一个String是流中的数据类型
                * 第二个String是转换后map的健的类型
            - 第二个参数函数式接口Function<String, String>:
                * 第一个String是流中的数据类型
                * 第二个String是转换后map的值的类型
         */
        Map<String, Integer> map = list.stream().collect(Collectors.toMap(new Function<String, String>() {
                                                                              @Override
                                                                              public String apply(String s) {
                                                                                  return s.split("-")[0];
                                                                              }
                                                                          },
                new Function<String, Integer>() {   //
                    @Override
                    public Integer apply(String s) {
                        return Integer.parseInt(s.split("-")[2]);
                    }
                }));

        System.out.println(map);  //{张强=21, 周芷若=20, 赵敏=20, 张无忌=18, 张蹒跚=21}

        //转换为HashMap - lambda写法
        Map<String, String> map2 = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toMap(
                s -> s.split("-")[0],
                s -> s.split("-")[2]));
        System.out.println(map2);  //{张强=21, 张无忌=18, 张蹒跚=21}
    }
}

Stream 总结

方法引用

什么是方法引用?

把已经存在的方法拿过来用,当作函数式接口中抽象方法的方法体

:: 是什么符号?

方法引用符

方法引用时要注意什么?

  • 需要有函数式接口
  • 被引用方法必须已经存在
  • 被引用方法的形参和返回值需要跟抽象方法保持一致
  • 被引用方法的功能要满足当前需求

静态方法引用

package com.study.streamdemo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;

public class StreamDemo4 {

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "1","2","3","4");
        
        //需求:将list中的数据转化为int
        
        list.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.parseInt(s);
            }
        });
        
        //list.stream().map(s -> Integer.parseInt(s)).forEach(s-> System.out.println(s));

        //lambda 写法
        list.stream().map(Integer::parseInt).forEach(s-> System.out.println(s));

    }
}

成员方法引用

package com.study.streamdemo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;

public class StreamDemo5 {

    /*
    引用成员方法:
        前提:引用的方法签名和函数式接口的签名一致
    1.其他类:其他类对象::方法
    2.本类: this::方法
    3.其他类: super::方法发
     */
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌","周芷若","赵敏","张强","张蹒跚");

        list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张") && s.length() == 3;
            }
        }).forEach(s -> System.out.println(s)); //张无忌,张蹒跚

        //  StringJudge 类的 stringJudge 签名要与filter函数参数的函数式接口签名一致
        list.stream().filter(new StringJudge()::stringJudge).forEach(s-> System.out.println(s)); //张无忌,张蹒跚
    }
}

class StringJudge{
    public boolean stringJudge(String s){
        return s.startsWith("张") && s.length() == 3;
    }
}

构造方法引用

package com.study.streamdemo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class StreamDemo6 {

    public static void main(String[] args) {
        
        //需求:将list中的字符串转换为Student对象
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌,16","周芷若,27","赵敏,24","张强,13","张蹒跚,21");

        //匿名内部类写法
        List<Student> list2 = list.stream().map(new Function<String, Student>() {
            @Override
            public Student apply(String s) {
                String[] split = s.split(",");

                return new Student(split[0],Integer.parseInt(split[1]));
            }
        }).collect(Collectors.toList());
        System.out.println(list2);


        //方法引用构造方法
        List<Student> collect = list.stream().map(Student::new).collect(Collectors.toList());
        System.out.println(collect);
        //[Student{name = 张无忌, age = 16}, Student{name = 周芷若, age = 27}, Student{name = 赵敏, age = 24}, Student{name = 张强, age = 13}, Student{name = 张蹒跚, age = 21}]
    }
}

类名引用成员方法

package com.study.streamdemo;

import java.util.ArrayList;
import java.util.Collections;

public class StreamDemo7 {


    /*
    引用格式:Class::实例方法
    该格式引用的规则:
    1.需要有函数式接口
    2.被引用的方法已经存在
    3.被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致
    4.被引用方法的功能需要满足当前需求

    抽象方法形参详解:
    1.第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法
                在Stream流中,第一个参数一般都表示流里卖弄的每一个元素
                假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法
    2.第二个参数到最后一个参数,跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用法的方法是无参的成员方法

     */
    public static void main(String[] args) {
        //需求:将list中的字符串转换小写
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "aaa","bbb","ccc","ddd","eee");

        list.stream().map(String::toUpperCase).forEach(s-> System.out.print(s)); //AAABBBCCCDDDEEE
    }
}

数组构造方法引用

package com.study.streamdemo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class StreamDemo8 {

    /*
    引用数组的构造方法
     */
    public static void main(String[] args) {

        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1, 2, 3, 4, 5);

        Integer[] integers = list.stream().toArray(Integer[]::new);
        System.out.println(Arrays.toString(integers));  //[1, 2, 3, 4, 5]
    }
}

方法引用总结

posted @ 2022-09-18 15:22  chuangzhou  阅读(35)  评论(0编辑  收藏  举报