带你了解Stream流

Stream流

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

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

1. 为什么要使用Sream流

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

一个ArrayList集合中存储有以下数据:张无忌,周芷若,赵敏,张强,张三丰

需求:

  1. 拿到所有姓张的。
  2. 拿到名字长度为3个字的。
  3. 打印这些数据。

传统的写法是:

public class Test01 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");
        // 1. 拿到所以姓张的
        ArrayList<String> zhangList = new ArrayList<>();
        for (String name : list) {
            if (name.startsWith("张")){
                zhangList.add(name);
            }
        }
        // 2. 拿到名字长度为3个字的
        ArrayList<String> threeList = new ArrayList<>();
        for (String name : zhangList) {
            if (name.length()==3){
                threeList.add(name);
            }
        }
        // 3. 打印这些数据
        for (String name : threeList) {
            System.out.println(name);
        }
    }
}

分析:

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

  1. 首先筛选所有姓张的人。
  2. 然后筛选名字有三个字的人。
  3. 最后进行对结果进行打印输出。

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

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

使用Stream流的写法:

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();
    Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");
    // 使用stream流
    list.stream()
            .filter(item->item.startsWith("张"))
            .filter(item->item.length()==3)
            .forEach(item-> System.out.println(item));
}

我们发现这种写法非常的简短。

stream流对集合的操作语法简介,性能比传统快。

2. Stream流的原理

**注意:**stream和I0流(lnputStream/0utputStream)没有任何关系。
Stream流式思想类似于工厂车间的"生产流水线",Stream流不是一种数据结构不保存数据,而是对数据进行加工处理。Stream可以看作是流水线上的一个工席。在流水线上,通过多个工席让一个原材料加工成一个商品。

原料—>工序1—>工序2—>工序n—>产品

3. 如何获取Stream流对象

有四种方式:

  1. 通过Collection对象的stream()或parallelStream()方法。
  2. 通过Arrays类的stream()方法。
  3. 通过Stream接口的of()、iterate()、generate()方法。
  4. 通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法
public class Test02 {
    public static void main(String[] args) {
        //通过集合对象调用stream()获取流
        List<String> list=new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        Stream<String> stream =list.stream();
        //通过Arrays数组工具类获取stream对象
        int[] arr={3,4,5 ,63,2,34};
        IntStream stream1= Arrays.stream(arr);
        //使用stream类中of方法
        Stream<String> stream2 = Stream.of("hello","world","spring","java");
        //LongStream
        LongStream range = LongStream.range(1,10);
        //上面都是获取的串行流。还可以获取并行流。如果流中的数据量足够大,并行流可以加快处速度。
        Stream<String> stringStream = list.parallelStream();

        // 可以多线程处理的Stream流
        // stringStream.forEach(item->System.out.println(item));
        // 可以用引用
        stringStream.forEach(System.out::println);
    }
    
}

4. Stream的常用api方法

中间操作api:一个操作的中间链,对数据源的数据进行操作。而这种操作的返回类型还是一个Stream对象。

终止操作api:一个终止操作,执行中间操作链,并产生结果,返回类型不在是stream流对象。

在这里插入图片描述

4.1 filter

filter(): 用于过滤 Stream 中的元素,参数是一个 Predicate 函数式接口,用于定义过滤条件。

public class Test03 {
    public static void main(String[]args){
        List<Person> personList =new ArrayList<>();
        personList.add(new Person("萧炎",18,"中国","男"));
        personList.add(new Person("Tom", 24,"美国", "男"));
        personList.add(new Person("Harley",22,"英国","女"));
        personList.add(new Person("美杜莎",20,"中国","女"));
        personList.add(new Person("韩立",22,"中国","男"));
        personList.add(new Person("南宫婉",21,"中国","女"));
        personList.add(new Person("罗峰",20,"中国","男"));
        personList.add(new Person("石昊",22,"中国","男"));

        // 找到年龄大于18岁的人并输出;filter()过滤器需要一个断言接口函数,断言接口返回true,获取该元素foreach(consumer)
        // 无论执行多少个中间操作,如果没有执行终止作,那么中间作都不会被执行。
        personList.stream()
                .filter(item->item.getAge()>18)
                .forEach(System.out::println);
    }
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Person{
    private String name;
    private int age;
    private String country;
    private String sex;
}

运行结果:

在这里插入图片描述

4.2 count

返回 Stream 中的元素个数。

		// 找出所有中国人的数量。--->filter过滤掉其他国家的人 count()终止操作
        Long count = personList.stream().
                filter(item -> item.getCountry().equals("中国")).count();
        System.out.println(count);

运行结果:

在这里插入图片描述

4.3 map

map–接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

//集合中每个元素只要名.map--->原来流中每个元素转换为另一种格式。
personList.stream()
        .map(item->{
            Map<String,Object> m=new HashMap<>();
            m.put("name",item.getName());
            m.put("age",item.getAge());
            return m;
        })
        .forEach(System.out::println);

运行结果:

在这里插入图片描述

4.4 sorted

对 Stream 中的元素进行排序,默认是自然排序(升序)。

//对流中元素排序
personList.stream()
        .sorted((o1,o2)->o1.getAge()-o2.getAge())
        .forEach(System.out::println);

运行结果:

在这里插入图片描述

4.5 max

使用 max() 方法来获取 Stream 中的最大值。这个方法可以应用于不同类型的 Stream,如 Stream<Integer>Stream<Double> 或者自定义对象类型的 Stream,只要你提供了适当的比较器(Comparator)。

// 查找最大年龄的人。max终止操作
Optional<Person> max = personList.stream().max((o1,o2)->o1.getAge()- o2.getAge());
System.out.println(max.get());

运行结果:

在这里插入图片描述

4.6 reduce

对 Stream 中的元素进行归约操作,得到一个结果。参数是一个 BinaryOperator 函数式接口,用于定义归约规则。

//求集合中所有人的年龄和。参数和返回类型必须一致
Optional<Integer> reduce = personList.stream()
        .map(item -> item.getAge())
        .reduce((a,b)->a + b);
System.out.println(reduce.get());
//求集合中所有人的年龄和再加10。第一个参数为初始值
Integer reduce1 = personList.stream()
        .map(item -> item.getAge())
        .reduce(10, (a, b) -> a + b);
System.out.println(reduce1);

运行结果:

在这里插入图片描述

4.7 collect

将 Stream 转换为其他形式,如 List、Set、Map 等。参数是一个 Collectors 类中提供的收集器。

//搜集方法 collect 它属于终止方法
// 年龄大于20日性别为女的
List<Person>collect=personList.stream().filter(item->item.getAge()>20)
        .filter(item->item.getSex().equals("女"))
        .collect(Collectors.toList());
System.out.println(collect);

运行结果:

在这里插入图片描述

4.8 allMatch、amyMatch

allMatch:检查 Stream 中的所有元素是否都符合给定的条件。参数是一个 Predicate 函数式接口。

anyMatch:检查 Stream 中是否至少有一个元素符合给定的条件。参数是一个 Predicate 函数式接口。

// 性别为女,年龄都大于20才为真
// findFirst match
/*Optional<Person> first = personList.parallelStream()
        .filter(item -> item.getSex().equals("女"))
        .findAny();*/
boolean b = personList.parallelStream()
        .filter(item -> item.getSex().equals("女"))
        .allMatch(item -> item.getAge()>= 20);
System.out.println(b);

运行结果:

在这里插入图片描述

  • 14
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值