Java Stream使用

循环遍历的弊端

  • 得益于lambda表达式所带来的函数式编程引入了Stream的概念
  • Java8 Lambda表达式专注于做什么而不是怎么做,针对for循环语句可以发现:
    • for循环的语法就是“怎么做”
    • for循环的循环体才是“做什么”

Stream写法

/*
使用Stream流的方式,遍历集合二,对集合中的数据进行过滤
*/
public class DemoStream {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("wjx");
        list.add("gyj");
        list.add("1");
        list.add("2");
        list.stream()
                .filter(name->name.startsWith("w"))
                .filter(name->name.length()==3)
                .forEach(name->System.out.println(name));
    }
}

关于Stream流的理解

  • 流式操作的filter、map、ship都是对函数模型进行操作,集合元素并没有被真正的处理,只有当中介方法count执行的时候,整个模型才会按照指定的策略执行操作

  • Stream实际上是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值)

  • Stream(流)是一个来自数据源的元素队列,Java中的Stream并不会存储元素,而是按需计算

  • 数据源流的来源,可以是集合,数组等

Stream两个基础特征

  • Pipelining:中间操作都会返回流对象的本身,这样多个操作可以穿成一个管道
  • 内部操作:以前对集合遍历都是通过iterator或者增强for的方式,显式的在集合外部进行迭代,这叫做外部迭代,Stream提供了内部迭代的方式,流可以直接调用遍历方法

使用步骤:

  • 获取一个数据源->数据转换->执行操作获取想要的结果 ,经过此转换原有Stream不发生改变,返回一个新的Stream对象。

获取流

  • 所有的Collection集合都可以通过Stream默认方法获取流
  • Stream接口的静态方法of可以获取数组对应的流
    • staticStreamof(T…values)参数是一个可变参数,可以传递一个数组

Stream常用方法

  • 常用方法分为
    • 延迟方法:返回值仍然是Stream接口的自身类型的方法,因此支持链式调用(除了终结方法外其他的都是延迟方法)
    • 终结方法:返回值的类型不再是Stream接口自身类型的方法,因此不再支持生成器模式那样的链式调用
forEach
void forEach(Comsumer<? super T> action)

eg:


/* forEach方法用来遍历流中的数据
* 但是这个方法为终结方法,遍历之后就不能继续调用Stream流中的其他方法
*/
public class Demo03Stream {
    public static void main(String[] args) {
        //获取 一个Stream流
        Stream<String> stream = Stream.of("wjx", "1","2","3");
        //使用Stream流 中的方法forEach流中的数据进行遍历
        stream.forEach(name-> System.out.println(name));
    }
}
过滤
//该方法产生一个boolean值结果,代表指定的条件是否满足,如果为true, 那么 Stream流的filter()方法就会留用这个元素,反之则舍弃
boolean test(T t)

eg:

public class Demo04Stream {
    public static void main(String[] args) {
        //创建一个Stream流
        Stream<String>stream = Stream.of("wjx", "11", "2", "3");
        //对Stream流中的元素进行过滤
        stream.filter(name->name.startsWith("w")).forEach(name-> System.out.println(name));
        /**
         * Stream属于管道流,只能消费一次
         * 第一个Stream流调用完毕方法,数据就会流转到写一个Stream上
         * 而这时第一个Stream流就会关闭
         * 所以第一个Stream流就不能在调用其他方法了
         * 数据流到下一步,上一步的流就会关闭
         */
//        stream.forEach(name-> System.out.println(name));
    }
}

映射

//将流中的元素映射到另一个流中,将一种T类型转换为R类型
<R> Stream<R> map(Function<?super T, ?extends<R> mapper)

eg:

public class Demo05Stream {
    public static void main(String[] args) {
        //获取一个String类型的Stream流
        Stream<String> stream = Stream.of("1", "2", "3","4");
        //使用map方法把字符串类型的整数,转换映射为Integer类型的整数
        stream.map(s->Integer.parseInt(s)).forEach(s-> System.out.println(s));
    }
}

统计个数

//终结方法
long count();

eg:

public class Demo06Stream {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("1", "2", "3");
        int count = (int) stream.count();
        System.out.println(count);
    }
}


截取流

//limit是一个延迟方法,只是对流中元素进行截取返回的是一个新的流
Stream<T> limit(long size)

eg:

public class Demo07Stream {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("1","2","3");
        stream.limit(2).forEach(ele-> System.out.println(ele));
    }
}

跳过前几个元素

//如果当前长度小于n,则跳过前n个元素,否则将返回一个长度为0的空流
Stream<T> skip(long n);

eg:

public class Demo08Stream {
    public static void main(String[] args) {
        Stream<String>stream = Stream.of("1","2","3");
        stream.skip(2).forEach(ele-> System.out.println(ele));
    }
}

合并流

//不去重
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T>b);

eg:


public class Demo09Stream {
    public static void main(String[] args) {
        Stream<String>stream = Stream.of("1","2","3");
        Stream<String> stream2 = Stream.of("3", "0", "9");
        Stream<String> stream3 = Stream.concat(stream, stream2);
        stream3.forEach(ele-> System.out.println(ele));

    }
}

猜你喜欢

转载自blog.csdn.net/qq_39424143/article/details/95198218