java学习笔记-Stream流以及方法引用

java学习笔记-Stream流以及方法引用

文章目录

  • java学习笔记-Stream流以及方法引用
    • 1.初始Stream流
      • 1.1样例
      • 1.2.Stream流的思想
      • 1.3 Stream流的方法
        • Stream流的中间方法
        • Stream流的终结方法
      • 1.4 综合练习
    • 2.方法引用
      • 2.1 介绍
      • 2.2 引用静态方法
      • 2.3 引用成员方法
      • 2.4 引用构造方法
      • 2.5 其他调用方式
      • 综合练习

1.初始Stream流

1.1样例

ArrayList<Integer> list = new ArrayList<>();
list.add(2);
list.add(10);
list.add(10);
list.add(3);
list.add(5);
list.stream().filter(a -> a % 2 == 0).forEach(a -> System.out.println(a));

以上代码就是获得集合数据中的偶数。

1.2.Stream流的思想

和工厂流水线工作差不多。

Stream可以通过结合Lambda表达式,简化集合、数组的操作。

主要步骤

  • 先得到一条Stream流,并把数据放上去。
  • 利用Stream流中的API进行各种操作(中间方法:过滤、转换;最终方法:统计、打印)。

那么如何使用一个Stream流呢?

获取方式 方法名 说明
单列集合 default Stream stream() Collection中的默认方法
双列集合 无,可以通过调用集合方法变为单列集合。 无法直接使用stream流
数组 public static Stream stream(T[] array) Arrays工具类中的静态方法
零散的数据 public static Stream of(T… values) Stream接口中的静态方法
//1.单列集合获取Stream流

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "a", "b", "c", "d", "e", "f", "g");
// 获取到一条流水线,并把集合中的数据放到流水线。
Stream<String> stream1 = list.stream();
//使用终结方法打印一下流水线上的数据
stream1.forEach(System.out::println);

//双列集合
// 创建双列集合
HashMap<String, Integer> mp = new HashMap<>();
mp.put("张三", 12);
mp.put("里斯", 29);
// 第一种获取Stream流的方法
mp.keySet().stream().forEach(System.out::println);
System.out.println("-----------------------");
// 第二种获取Stream流的方法
mp.entrySet().stream().forEach(System.out::println);
//数组获取Stream流
Integer[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Stream<Integer> stream1 = Arrays.stream(arr);

stream1.filter(a -> a % 2 == 0).forEach(System.out::println);
//一堆零散的数据,引用类型以及基本类型都可以
Stream<Integer> integerStream = Stream.of(1, 2, 3, 3, 4, 5);
integerStream.filter(a -> a > 3).forEach(System.out::println);

细节

stream接口中的静态方法of,方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组。

但是数组必须引用数据类型的,如果传递基本数据类型,会把整个数组当作一个元素,放在stream中。

1.3 Stream流的方法

Stream流的中间方法
方法名 说明
Stream filter(Predicate predicate) 过滤
Stream limit(long maxSize) 获取前几个元素
Stream skip(long n) 跳过前几个元素
Stream distinct() 元素去重,依赖(hascode和equals方法)
static Stream concat(Stream a, Stream b) 合并a和b两个流为一个流,尽可能数据类型一致
Stream map(Function mapper) 转换流中的数据类型

注意1:中间方法,返回新的Stream流,原来的流只能使用一次,可以使用链式编程

注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据

以map函数为例:

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张三-12", "李四-35", "赵武-56");
Stream<String> stream1 = list.stream();
stream1.map(new Function<String, Integer>() {

    @Override
    public Integer apply(String s) {
        String[] arr = s.split("-");
        return Integer.parseInt(arr[1]);
    }
}).forEach(System.out::println);

结果为:

12
35 
56
Stream流的终结方法
方法名 说明
void forEach(Consumer action) 遍历
long count() 统计
toArray() 收集流中的数据,放到数组中
collect(Collector collector) 收集流中的数据,放到集合中
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张三-12", "李四-35", "赵武-56");
Stream<String> stream1 = list.stream();
//返回值,如果无参数,那返回Object数组
//如果有参数,参数作用是负责创建一个指定类型的数组,
//底层会依次得到流里面的每一个数据,并把数据放到数组当中
String[] res = stream1.toArray(new IntFunction<String[]>() {
    @Override
    public String[] apply(int value) {
        return new String[value];
    }
});
System.out.println(Arrays.toString(res));

collect详细解释

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张三-12", "李四-35", "赵武-56");
Stream<String> stream1 = list.stream();
//把年龄大于30的收集起来,先进行过滤,然后进行收集,调用Collectors.toList()
List<String> new_list = stream1.filter(s -> Integer.parseInt(s.split("-")[1]) > 30).collect(Collectors.toList());
System.out.println(new_list);

收集到list中,使用Collectors.toList()

收集到Set,使用Collectors.toSet(),与list相比,set会去除重复元素。

收集到map,使用 Collectors.toMap ()注意:键值不能重复

Map<String, Integer> mp = stream1.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("-")[1]);
    }
}));

等价于用lambda表达式(只有函数式接口才能进行lambda简化)

Map<String, Integer> mp = stream1.collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[1])));

1.4 综合练习

java学习笔记-Stream流以及方法引用_第1张图片

package com.demo;

import java.math.BigInteger;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Test {

    public static void main(String[] args) {

        ArrayList<String> boy = new ArrayList<>();
        ArrayList<String> girl = new ArrayList<>();
        Collections.addAll(boy, "李一封,35", "菜许坤,31", "五一饭,27", "罗想,37");
        Collections.addAll(girl, "杨米,18", "杨樱花,28", "刘一飞,18", "高元元,18");
        Stream<String> stream = Stream.concat(boy.stream().filter(s -> s.split(",")[0].length() == 3).limit(2),
                girl.stream().filter(s -> s.startsWith("杨")));
        List<Actor> actors = stream.map(s -> new Actor(s.split(",")[0], Integer.parseInt(s.split(",")[1])))
                .collect(Collectors.toList());
        for (Actor actor : actors) {
            System.out.println("name:" + actor.getName() + " age:" + actor.getAge());
        }
    }

}

class Actor{
    private String name;
    private int age;
    public Actor(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

2.方法引用

2.1 介绍

把已经存在的方法当做函数式接口中抽象方法的方法体。

函数式接口是只有一个抽象方法的接口

Arrays.sort(arr, class_name::subcmp);
public static int subcmp(int n1, int n2) {
	return n2 - n1;
}
  • 引用处必须是函数式接口
  • 被引用的方法必须已经存在
  • 被引用方法的形参和返回值需要和抽象方法保持一致
  • 被引用方法的功能需要满足当前要求

2.2 引用静态方法

格式:类名::静态方法

范例:Integer::parseInt

//"1", "2", "3", "4" 变成整型
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3", "4" 变成整型);
list.stream().map(Integer::parseInt).forEach(System.out::println);

2.3 引用成员方法

格式:对象::成员方法

  • 其他类: 其他类对象::方法名
  • 本类: this::方法名
  • 父类: super::方法名()

本类以及父类在非静态方法中调用

2.4 引用构造方法

格式:类名::new

范例:Student::new

为了创建对象。

ArrayList<String> boy = new ArrayList<>();
ArrayList<String> girl = new ArrayList<>();
Collections.addAll(boy, "李一封,35", "菜许坤,31", "五一饭,27", "罗想,37");
Collections.addAll(girl, "杨米,18", "杨樱花,28", "刘一飞,18", "高元元,18");
Stream<String> stream = Stream.concat(boy.stream().filter(s -> s.split(",")[0].length() == 3).limit(2),
        girl.stream().filter(s -> s.startsWith("杨")));
List<Actor> actors = stream.map(Actor::new)))
        .collect(Collectors.toList());
for (Actor actor : actors) {
    System.out.println("name:" + actor.getName() + " age:" + actor.getAge());
}

class Actor{
    private String name;
    private int age;
    public Actor(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Actor(String s) { //新加的
        this.name = s.split(",")[0];
        this.age = Integer.parseInt(s.split(",")[1]));
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

2.5 其他调用方式

类名引用成员方法

格式:类名::成员方法

范例:String::substring

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "aaaa", "bbb", "ccc");
list.stream().map(String::toUpperCase).forEach(System.out::println);

规则:

  • 函数接口
  • 被引用的方法必须存在
  • 被引用方法的形参,需要跟抽象方法的第二个参数到最后一个形参保持一致,返回值需要保持一致。
  • 被引用方法需要满足当前的需求

抽象方法形参的详解:

第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法。在Stream流中,第一个参数一般都表示流里面的每一个数据。

引用数组的构造方法

格式:数据类型[]::new

范例:int[]::new

ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3);
Integer[] arr = list.stream().toArray(Integer[]::new);

数组的类型要和流中的数据类型保持一致。

综合练习

创建集合添加学生对象,name,age

获取姓名并放到数组中

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

public class Func {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张三,18", "李四,20", "王五,21");
        String[] name = list.stream().map(Student::new).map(Student::getName).toArray(String[]::new);
        System.out.println(Arrays.toString(name));
    }
}
class Student {
    private String name;
    private int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Student(String str) {
        this.name = str.split(",")[0];
        this.age = Integer.parseInt(str.split(",")[1]);
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

你可能感兴趣的:(java学习笔记,java,学习,笔记)