Java学习day08--方法引用和Stream流

方法引用和Stream流

1).流思想:类似于“迭代器”,对“集合元素”进行多次的筛选、过滤、统计用的。
2).流的工作方式:每个操作后,这个流对象就成为垃圾,等待被回收;但这个操作的方法通常会返回一个新流--每个“流对象”都是一次性的。类似于:流水线。
3).Stream流中大量运用lambda表达式,对于某些lambda表达式而言,可以利用方法引用替换lambda表达式,从而再次简化代码。
4).方法引用是指,当我们要编写一个Lambda表达式时,发现已经有一个现有的方法已经实现了我们在Lambda中要实现的功能,这时就可以引用这个已写好的方法,来代替我们的Lambda表达式。

方法引用

我们首先创建一个类,以下所有内容讲解都基于这个类

public class Student {
    private String name;
    private int age;
    // 构造方法引用
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 构造方法引用
    public Student(String name){
        this.name = name;
        this.age = 20;
    }
    // 构造方法引用
    public Student() {
        this("热巴", 18);
    }
    // 利用这个实例化方法引用
    public String getName() {
        return name;
    }
    
   // 利用这个静态方法引用
    public static boolean func1(String s){
        return s.length() > 2;
    }
}
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
  1. 实例方法引用
    格式,对象名::函数名
Student stu = new Student("杨幂", 19);
// 实例化方法引用
func(stu::getName);        // 这里利用实例化对象调用show方法,可以不用自己再写lambda表达式
        
public static void func(Supplier<String> sp){
        String str = sp.get();
        System.out.println(str);
    }
  1. 静态方法引用
    格式,类名::函数名
    注意:该方法应用只能通过类名调用,实例化对象不可调用
// 静态方法引用
func1(Student::func1, "杨幂");     // 调用Student类中func1静态方法

public static void func1(Predicate<String> sp, String str){
        boolean b = sp.test(str);
        System.out.println(b);
    }
  1. 引用对象的构造方法
    不管是无参构造还是有参构造,格式写法相同,程序会自动判断选择哪个构造函数。写法为类名::new,如Student::new
// 引用构造方法--有参数
func2(Student::new, "刘亦菲");   // 这个会自动选择有一个参数的构造方法
// 引用构造方法--无参数
func3(Student::new);    // // 这个会自动选择无参数的构造方法

public static void func2(Function<String, Student> f, String str){
        Student student = f.apply(str);
        System.out.println(student);
    }

public static void func3(Supplier<Student> sp){
    Student student = sp.get();
    System.out.println(student);
}
  1. 数组构造器引用
    格式:类型名[]::new
// 数组构造器引用
 func4(int[]::new, 4);             

public static void func4(Function<Integer, int[]> f, Integer integer){
        int[] arr = f.apply(integer);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i * 2 + 1;
        }
        System.out.println(Arrays.toString(arr));
    }

获取Collection、Map、数组流

  1. Collection流的获取
    通过Collection接口的默认方法stream(),具体调用格式为Collection对象.stream()即可获取。如:
ArrayList<String> list = new ArrayList<>();
list.stream();          // 返回结果即为流对象
  1. Map获取流
    有三种获取流的方式
// 方式一:获取键的流
Map<String, Integer> map = new HashedMap<>();
map.keySet().stream();

// 方式二:获取值的流
map.values().stream();

// 方式三:获取键值对的流
map.entrySet.stream();
  1. 获取数组的流
    这里又分为两种,一种是获取引用类型的流,另一种是获取基本类型的流。
// 第一种:获取基本类型的流
IntStream.of(arr);     // arr为对应类型的数组,如此处为int类型的数组
LongStream.of(arr);
DoubleStream.of(arr);

// 第二种:获取引用类型的流
Stream.of(arr)      // arr为引用类型的数组

4.零散的数据获取流

Stream<Integer> s = Stream.of(1, 23, 4, 5, 7, 8, 9, 0, 8);

Stream流的常用操作方法

  1. 逐一处理forEach
void forEach(Consumer<? super T> action);   // 方法原型

示例代码:

ArrayList<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");

// 1. forEach逐一处理
list.stream().forEach(s -> System.out.println(s + "是好样的"));  // 在每一个元素后面加“好样的”
程序结果为:
张无忌是好样的
周芷若是好样的
赵敏是好样的
张强是好样的
张三丰是好样的
  1. 过滤filter
Stream<T> filter(Predicate<? super T> predicate);   // 方法原型

示例代码:

// 先 筛选姓“张”的,再在尾部加上“是好样的”
list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s + "是好样的"));
结果为:
张无忌是好样的
张强是好样的
张三丰是好样的
  1. 计数count
long count();    // 方法原型

示例代码:

// 获取姓张的一共有几个
long num = list.stream().filter(s -> s.startsWith("张")).count();  
System.out.println("张姓的一共有" + num + "个");
结果为:
张姓的一共有3个
  1. 取出前几个limit
Stream<T> limit(long maxSize);   // 方法原型

示例代码:

// 获取张姓的前一个并打印
list.stream().filter(s -> s.startsWith("张")).limit(1).forEach(System.out::println);
结果为:
张无忌
  1. 跳过前几个skip
Stream<T> skip(long n);   //  方法原型

示例代码:

获取张姓的除了一个并打印
list.stream().filter(s -> s.startsWith("张")).skip(1).forEach(System.out::println);
  1. 映射(转换)map
<R> Stream<R> map(Function<? super T, ? extends R> mapper); // 函数原型

示例代码:

ArrayList<String> list1 = new ArrayList<>();
list1.add("123");
list1.add("456");
list1.add("789");
list1.add("101");
// 将String先转为Int类型,再打印加5的值。以下两种写法均可,任选其一即可
list1.stream().map(s -> Integer.valueOf(s)).forEach(s -> System.out.println(s + 5));
list1.stream().map(Integer::parseInt).forEach(s -> System.out.println(s + 5));
  1. 合并concat
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)   // 函数原型,是一个静态方法

示例代码:

// 将list和list1的流合并
Stream.concat(list.stream(), list1.stream()).forEach(System.out::println);
  1. 将Stream流结果转换为各种集合之collect方法
Stream<String> stream = list.stream();
// 转为List类型
stream.collect(Collectors.toList());

//  转为Set类型
stream.collect(Collectors.toSet());

// 转为数组
stream.toArray(类型名[]::new);

注:

  • 拼接方法,返回一个新流;
  • 终结方法,返回的是最终的值。
    前面讲的count和forEach方法为终结方法,其余的均是拼接方法(也除了collection方法)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值