Java8中Stream流的详细用法

目录

1.为什么使用stream流

2. Stream流的原理

3.步骤

4.获取Stream流对象的方式

5.Stream流的api方法

 filter:过滤

 forEach:结束

 count():计算

min:最小

max:最大

collect:收集

sorted:排序

findFirst:返回流中的第一个

findAny:返回流中的任意一个

anyMatch:是否存在满足指定条件

allMatch:所有元素是否都满足指定条件

map:计算或转换

reduce:归约

6.注意事项



Java8的两个重大改变,一个是Lambda表达式,另一个就是的Stream API表达式

Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找、过滤、筛选等操作

1.为什么使用stream流

当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。我们来体验 集合操作数据的弊端,需求如下:

案例:

一个ArrayList集合中存储有以下数据:张三,王五,王小二,王老五,李四
需求:1.拿到所有姓王的 2.拿到名字长度为3个字的 3.打印这些数据

public class Test01 {
    public static void main(String[] args) {
        //需求:1.拿到所有王姓  2.拿到名字长度为3个字的  3.打印
        List list = new ArrayList<>();
        list.add("张三");
        list.add("王五");
        list.add("王小二");
        list.add("王老五");
        list.add("李四");

        //1.拿到王姓
        List list01 = new ArrayList<>();
        for (String n : list){
            if (n.startsWith("王")){  //startsWith:开头为王
                list01.add(n);
            }
        }

        //2.拿到名字长度为3个字的
        List list02 = new ArrayList<>();
        for (String n : list01){
            if (n.length()==3){  //长度为3个字的
                list02.add(n);
            }
        }
        //3.打印
        for (String s : list02){
            System.out.println(s);
        }

    }
}

分析:

循环遍历的弊端

这段代码中含有三个循环,每一个作用不同:

  1. 首先筛选所有姓王的人;

  2. 然后筛选名字有三个字的人;

  3. 最后进行对结果进行打印输出。

每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环 是做事情的方式,而不是目的。每个需求都要循环一次,还要搞一个新集合来装数据,如果希望再次遍历,只能再使 用另一个循环从头开始。

那Stream能给我们带来怎样更加优雅的写法呢?

Stream初体验

public class Test01 {
    public static void main(String[] args) {
        //需求:1.拿到所有王姓  2.拿到名字长度为3个字的  3.打印
        List list = new ArrayList<>();
        list.add("张三");
        list.add("王五");
        list.add("王小二");
        list.add("王老五");
        list.add("李四");

        //stream流完成
        list.stream().filter(t->t.startsWith("王")).filter(t->t.length()==3).forEach(System.out::println);

    }
}

2. Stream流的原理

Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工 处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

Java8中Stream流的详细用法_第1张图片

3.步骤

  1. 获取Stream流对象
  2. 中间操作---返回类型还是Stream流对象。
  3. 终止操作---不在是Stream流对象Java8中Stream流的详细用法_第2张图片

4.获取Stream流对象的方式

  • 通过集合对象调用stream()
  • 通过Arrays获取stream流对象
  • 通过Stream流里面of方法

实例:

public class Test02 {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        //第一种:通过集合对象调用stream
        Stream stream = list.stream();//获取Stream流
        stream.forEach(System.out::println);  //打印
        
        //第二种:通过Arrays获取stream流对象
        String[] arr = {};
        Stream stream1 = Arrays.stream(arr);

        //第三种:通过Stream流里面of方法
        Stream integerStream = Stream.of(1, 2, 3, 4);


        //上面三种流都是串行流。    并行流:
        Stream stringStream = list.parallelStream();
        stringStream.forEach(System.out::println);
    }
}

5.Stream流的api方法

 filter:过滤

 filter:根据指定的条件过滤流中的元素,只保留满足条件的元素

 forEach:结束

 forEach:对流中的每个元素执行指定的操作,处理完所有元素后才结束

 count():计算

 count():计算流中元素的数量,处理完所有元素后返回数量值

min:最小

min: 根据指定的比较器,找到流中的最小元素,处理完所有元素后返回最小元素

max:最大

 max: 根据指定的比较器,找到流中的最大元素,处理完所有元素后返回最大元素

collect:收集

collect: 根据指定的收集器,将流中的元素进行收集操作,处理完所有元素后返回一个结果对象。

sorted:排序

sorted(): 对流中的元素进行排序,需要保持状态来进行排序操作。

findFirst:返回流中的第一个

findFirst(): 返回流中的第一个元素,如果流为空则返回一个空的Optional对象。

findAny:返回流中的任意一个


findAny(): 返回流中的任意一个元素,如果流为空则返回一个空的Optional对象

anyMatch:是否存在满足指定条件

anyMatch 判断流中是否存在满足指定条件的元素,一旦找到满足条件的元素,立即返回true,不再继续处理剩余元素。

allMatch:所有元素是否都满足指定条件

allMatch 判断流中的所有元素是否都满足指定条件,一旦发现有不满足条件的元素,立即返回false,不再继续处理剩余元素。

 
   

案例:

public class Test03 {
    public static void main(String[] args) {
        //举个简单的例子:
        //假设有一个Person类和一个Person列表
        // 现在有两个需求:1)找到年龄大于18岁的人并输出;2)找出所有中国人的数量
        List personList = new ArrayList<>();
        personList.add(new Person("欧阳雪", 18, "中国", 'F'));
        personList.add(new Person("Tom", 24, "美国", 'M'));
        personList.add(new Person("Harley", 22, "英国", 'F'));
        personList.add(new Person("向天笑", 20, "中国", 'M'));
        personList.add(new Person("李康", 22, "中国", 'M'));
        personList.add(new Person("小梅", 20, "中国", 'F'));
        personList.add(new Person("何雪", 21, "中国", 'F'));
        personList.add(new Person("李康", 22, "中国", 'M'));
        //1. 年龄大于18  filter:过滤掉不满足条件的元素.  forEach:输出元素. ---如果没有终止函数,那么中间函数的代码不会被执行。
        personList.stream().filter(item -> {
            System.out.println("=======");
            return item.getAge() > 18;
        }).forEach(System.out::println);

        //2. 找出中国人  并统计个数: count()
        long count1 = personList.stream().filter(item -> item.getCountry().equals("中国")).count();
        System.out.println("中国人:" + count1);

        //找出年龄最大和最小
        Person person = personList.stream().max(((o1, o2) -> o1.getAge() - o2.getAge())).get();
        Person person2 = personList.stream().min(((o1, o2) -> o1.getAge() - o2.getAge())).get();
        System.out.println(person);
        System.out.println(person2);

  //把Person-年龄大于20人--里面名称----新的集合。
        List collect = personList.stream().filter(item -> item.getAge() > 20).map(item -> item.getName()).collect(Collectors.toList());
        System.out.println(collect);


//sorted排序 按照年龄从小到大排序
        List collect = personList.stream().sorted((o1, o2) -> o1.getAge() - o2.getAge()).collect(Collectors.toList());
        System.out.println(collect);

//findFirst(): 返回流中的第一个元素,如果流为空则返回一个空的Optional对象。
        Optional first = personList.stream().filter(item->item.getAge()>=20&&item.getAge()<=24).findFirst();
        System.out.println(first.get());

        //findAny(): 返回流中的任意一个元素,如果流为空则返回一个空的Optional对象
        Optional any = personList.stream().filter(item -> item.getAge() > 20).findAny();
        System.out.println(any.get());


 //anyMatch 判断流中是否存在满足指定条件的元素,一旦找到满足条件的元素,立即返回true,不再继续处理剩余元素。
        //判断有没有姓名为小梅的
        boolean b = personList.stream().anyMatch(a -> a.getName().equals("小梅"));
        System.out.println(b);

        //allMatch 判断流中的所有元素是否都满足指定条件,一旦发现有不满足条件的元素,立即返回false,不再继续处理剩余元素。
        //判断是不是所有姓名都叫小梅
        boolean b2 = personList.stream().allMatch(a -> a.getName().equals("小梅"));
        System.out.println(b2);
    }
}


@Data
@NoArgsConstructor
@AllArgsConstructor
class Person {
    private String name;
    private Integer age;
    private String country;
    private char sex;
}

map:计算或转换

 map: 可以把对流中的元素进行计算或转换

public class Test04 {

        public static void main(String[] args) {
            //整数数组每个元素+3
            List list = Arrays.asList(1, 17, 27, 7);
            list.stream().map(item->item+3).forEach(System.out::println);

            List list2=Arrays.asList("hello","world","java","spring","springmvc");
            //字符串大写
            list2.stream().map(String::toUpperCase).forEach(System.out::println);
        }
}

reduce:归约

reduce:归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。

Java8中Stream流的详细用法_第3张图片


 List list= Arrays.asList(1,2,3,5);
 Optional reduce = list.stream().reduce((t1, t2) -> t1 * t2); //求积
System.out.println(reduce);

6.注意事项

  • 惰性求值(如果没有终结操作,没有中间操作是不会得到执行的)

  • 流是一次性的(一旦一个流对象经过一个终结操作后。这个流就不能再被使用)

 
  • 不会影响原数据(我们在流中可以多数据做很多处理。但是正常情况下是不会影响原来集合中的元素的。这往往也是我们期望的)

你可能感兴趣的:(java,开发语言)