JAVA--高级基础开发

时光总嘲笑我的痴心妄想 提交于 2019-12-05 03:48:00

day09[Stream 流,方法引用]

第一章: Stream流

这里的 Stream,是在 Java 8 中,因为 Lambda 带来的函数式编程,引入的一个全新的 Stream 概念,用于解决已有集合中既有的弊端。

    1. 概述
  1. 传统集合的遍历代码,几乎所有的集合(Collection,Map 等)都支持间接或直接的遍历操作,而当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合的遍历。

//传统的写法

public class Test1{

    public static void main(String[] args) {

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

        list.add("李文杰");

        list.add("李文集");

        list.add("李文洁");

        list.add("王智雅");

        list.add("何舒雅");

        list.add("王文文");

        //传统的写法

        for(String  ss:list){

          System.out.println(ss);

            }

        }

这是一段非常简单的集合遍历操作,集合中的字符串都进行输出操作

    1. for循环遍历的弊端
  1. 为什么使用循环?因为要进行遍历,但循环是遍历的唯一方式吗?遍历是指每一个元素逐一进行处理,而并不是从第一个到最后一个顺次处理的循环,前者是目的,后者是方式。
  2. 试想一下,如果希望对集合中的元素进行筛选过滤:
  3. 1、将集合 A 根据条件过滤为子集合 B
  4. 2、然后在根据条件过滤为子集合 C

Java jdk8 之前的代码:

 

public class Test1{

    public static void main(String[] args) {

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

        list.add("李文杰");

        list.add("李文集");

        list.add("李文洁");

        list.add("王智雅");

        list.add("何舒雅");

        list.add("王文文");

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

        //传统的写法

        for(String  ss:list){

            if(ss.startsWith("李")){

                li.add(ss);

            }

        }

        for(String  ss2: li){

            System.out.println(ss2);

        }

}

}

分析这段代码中两个 for 循环:

1、 首先筛选所有姓李的人

2、 然后存入到新的集合中

3、 最后进行筛选结果的输出

每当我们需要对集合中的元素进行操作的时候,总是需要进行循环,循环,再循环。循环只 是做事的方式而不是目的,另一方面,使用线性循环就意味着只能遍历一次,如果希望再次

遍历,只能在执行一次代码。

  • Lambda 的衍生物 Stream 能给我带来更加优雅简洁的写法

Stream流的优雅写法

//体验Stream 流

public class Test1{

    public static void main(String[] args) {

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

        list.add("李文杰");

        list.add("李文集");

        list.add("李文洁");

        list.add("王智雅");

        list.add("何舒雅");

        list.add("王文文");

//使用Stream 流输出

        list.stream().filter(s->s.startsWith("")).

filter(s->s.length()==3).forEach(s->System.out.println(s));

//foreach 代表的就是for循环

    }

}

总结为: 获取流,过滤流,过滤流,开头为李,长度为 3,逐一输出,代码中并没有体现使用线性循环或其他任何算法进行遍历。

    1. 流式思想的概述
  • 整体来看,流式思想类似于工厂车间的“生产流水线”。
  • Stream 流其实就是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身也不存储任何元素。
  1. Stream 流是一个来自数据源的元素队列。
  • 元素是特定类型的对象,形成一个队列,java 中的 Stream 流不存储元素,而是按需计算。
  • 数据域流的来源,可以是集合、数组等。
  • 当使用一个流的时候,通常包括三个基本步骤:
  • 获取一个数据源-->数据转换,执行操作获取想要的结果,每次转换原有 Stream 流对象不改变,返回一个新的 Stream 对象,这就允许对其操作可以像链条一样排列,形成一个管道。
    1. 获取流Stream
  1. 位于java.util.stream 包中,interface Stream<T>接口是 Java 8 新加入的最常用的流接口(这并不是一个函数式接口)
  1. List集合 Set集合 数组获取流的方法:
  2. 获取一个流非常简单,有以下几种常用方式:
  3. 所有的 Collection 集合(List,Set)都可以通过 stream 默认方法获取流。
  4. Stream 接口的静态方法 of 可以获取数组对应的流.

//Collection 集合获取Stream流

public class Test2 {

    public static void main(String[] args) {

 //List集合获取流

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

        Stream<String>listStream=list.stream();

 

        //Set集合获取流

        Set<String>set=new HashSet<>();

        Stream<String>setStream=set.stream();

 

        //数组获取流Stream

        String[]array={"13","34","65","76","23"};

        Stream<String>stream=Stream.of(array);

    }

}

  1. 根据Map集合获取流:
  • java.util.Map 接口不是 Collection 的子接口,其 K-V 数据结构不符合流元素的单一特征,所以获取对应的流需要分 key、value 或 entry 等情况。

//Map集合获取流Stream流

public class Test2 {

public static void main(String[] args) {

//Map集合获取流

        Map<String,String>map=new HashMap<>();

        //Map集合Stream流获取键

        Stream<String>mapStream=map.keySet().stream();

        //Map集合Stream流获取值

        Stream<String>maps=map.values().stream();

        //Map集合通过EntrySet来获取Stream流,得到键和值

        Stream<Map.Entry<String,String>>entry=map.entrySet().stream();

}

}

 

    1. 常用的方法
  1. 延迟方法:返回值类型任然是一个 Stream 对象,因此支持链式调用(除了终结方法以

外,其余方法都是延迟方法) 

  1. 终结方法:返回值类型不再是 Stream 接口,因此不再支持链式调用。

1.6  Foreach

  1. 虽然名字叫foreach,但是与增强的for循环不同。

void  forEach(Consumer<? super T> action) d

该方法接收一个Consumer接口的函数,会将每一个流元素交给函数进行处理

基本使用:

public class Test3 {

    public static void main(String[] args) {

        //foreach示例

        Stream<String>stream=Stream.of("李文杰","张文集","王兰君","李军帽");

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

    }

}

1.7  Filter

过滤:可以通过Filter方法将一个流转换为另一个流

Stream<T> filter(Predicate<? super T> predicate) 

该方法接收一个 Predicate 函数式接口参数

基本使用:

public class Test3 {

    public static void main(String[] args) {

          //Fifter过滤器

Stream<String>stream=Stream.of("李文杰","张文集","王兰君","李军帽");

        Stream<String>newstream=stream.filter(s ->s.startsWith("李"));

        newstream.forEach(s -> System.out.println(s));

    }

}

 

1.8  map映射

1 如果需要将流中的元素映射到另一个流中,可以使用 map 方法.

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

基本使用:

public class Test3 {

    public static void main(String[] args) {

        //map映射

        Stream<String>stream1=Stream.of("12","34","45","66","99");

        Stream<Integer>stream2=stream1.map(s ->Integer.parseInt(s));

        stream2.forEach(s-> System.out.println(s+10));

}

}

1.9 count 统计个数

流通过count方法来计算流中的个数

long  count(); 返回此流中的元素数。

基本使用

//count方法的使用。

public class Test3 {

 public static void main(String[] args) {

//count方法来统计流的个数

        Stream<String>stream3=Stream.of("刘备","张飞","卧龙","凤雏");

        System.out.println("统计流的个数:"+stream3.count());

}

}

2.0  Limit 提取前几个元素

Limit 方法可以对流进行截取,只取前n个。

Stream<T> limit(long maxSize) 

基本使用:

public class Test3 {

public static void main(String[] args) {

//limit方法使用,对流进行截取

      Stream<String>stream4=Stream.of("赵云","关羽","黄忠","马超");

        Stream<String>stream5=stream4.limit(3);

        stream5.forEach(s -> System.out.println(s));

    }

}

2.1 Skip 跳过前几个元素

Skip方法可以对流实现跳过的操作,继续执行以下的数据

Stream<T> skip (long n) ;

如果流的当前长度大于 n,则跳过前 n 个,否则将会得到一个长度为 0 的空流

基本使用:

public class Test3 {

public static void main(String[] args) {

//Skip方法实现对流元素的跳过

        Stream<String>stream5=Stream.of("赵云","关羽","黄忠","马超");

        Stream<String>stream6=stream5.skip(2);

        stream6.forEach(s -> System.out.println(s));

    }

}

2.2 concat组合

如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口静态方法 concat

static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) 

基本使用:

public class Test3 {

public static void main(String[] args) {

    //concat 如果两个流,希望合并为一个流,那么就可以进行组合

        Stream<String>stream7=Stream.of("马超");

        Stream<String>stream8=Stream.of("西凉人");

        Stream<String>stream9=Stream.concat(stream7,stream8);

        stream9.forEach(s -> System.out.println(s));}

}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!