jdk8新特性之Stream流

目录

 

一、使用传统集合多步遍历与Stream流方式进行遍历

1.1使用传统方式遍历集合对集合进行过滤

1.2 Stream进行优化

二、什么是Stream

2.1 Stream(流)是一个来自数据源的元素队列并支持聚合操作

2.2特点

三、生成流

3.1 通过Collection的Stream()(串行流)方法或者parallelstream()(并行流)方法创建Stream

3.2 stream接口的静态方法0f可以获取数组对应的流

3.3 通过Arrays中得静态方法stream()获取数组流

3.4 创建无限流(迭代、生成)

四、Stream流中常用方法

4.1Stream流中API方法分为两类

4.2 forEach

4.3 过滤 filter

4.4 映射 map

4.5 统计个数: count

4.6 取用前几个: limit

4.7跳过前几个: skip

4.8 组合 concat

4.9 并行(parallel)程序

4.10 Collectors

4.11 统计

五、练习

 


一、使用传统集合多步遍历与Stream流方式进行遍历

1.1使用传统方式遍历集合对集合进行过滤

public class DemoList {
public static void main(String[] args) {
//    创建list集合,存储姓名
    List<String> list = new ArrayList<>();
    list.add("lily");
    list.add("linda");
    list.add("bom");
    
//    对list集合中的元素进行过滤率,只要以l开头就存储到新的集合中
    List<String> listA = new ArrayList<>();
    for (String s : list) {
        if(s.startsWith("l")) {
            listA.add(s);
        }
    }
    
//    对listA集合进行过滤,姓名长度为4,存储到新集合中
    List<String> listB = new ArrayList<>();
    for (String s : listA) {
        if(s.length() == 4) {
            listB.add(s);
        }
        
    }
//    遍历listB集合
    for (String s : listB) {
        System.out.println(s);

    }
    
}

}
 

这个练习用了三个循环。Stream的更优写法:

1.2 Stream进行优化

public class DemoList {
public static void main(String[] args) {
//    创建list集合,存储姓名
    List<String> list = new ArrayList<>();
    list.add("lily");
    list.add("linda");
    list.add("bom");
    
//    对list集合中的元素进行过滤率,只要以l开头就存储到新的集合中    
//    对listA集合进行过滤,姓名长度为4,存储到新集合
//    便利listB集合
    list.stream().filter(name -> name.startsWith("l"))
                 .filter(name -> name.length() == 4)
                 .forEach(name -> System.out.println(name));
    
}

}
 

filter中传的参数是Predicate(j进行判断)所以可以传递lambda

forEach中传的参数是Consumer(消费一个数据),同样也可以传递lambda

二、什么是Stream

2.1 Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(lambda)(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

2.2特点

Stream流属于管道流,只能被消费(使用)一次

第一个Stream流调用完毕方法,数据就会转到下一个Stream上

而这时Stream流已经使用完毕,就会关闭了

所以第一个Stream流就不在调用方法了

//    创建一个Stream流
    Stream<String> stream = Stream.of("lily","linda","bom");
//    对流中的元素进行过滤,只要l
    Stream<String> stream2 = stream.filter(name -> name.startsWith("l"));
//    对stream2进行遍历
    stream2.forEach(name -> System.out.println(name));

再次使用stream流进行遍历

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

运行后:

stream has already been operated upon or closed

三、生成流

3.1 通过Collection的Stream()(串行流)方法或者parallelstream()(并行流)方法创建Stream

default stream<E> stream()

//把集合转换成Stream流
    List<String> list = new ArrayList<>();
    Stream<String> stream = list.stream();
    Stream<String> stream1 = list.parallelStream();

对map进行操作

Map<String, String> map = new HashMap<String, String>();
//。获取键,存储到一个set集和
Set<String> keyset = map.keySet();
Stream<String> stream = keyset.stream();
//。获取值,存储到一个collection集合中
Collection<String> values = map.values();
Stream<String> stream2 = values.stream();
//。获取键值对,键与值是映射关系,entrySet
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<String> stream3 = entries.stream();
    

3.2 stream接口的静态方法0f可以获取数组对应的流

static <T> Stream <T> of (T ... values)

//将数组转换为Stream流
    Stream<Integer> stream = Stream.of(1,2,3,4,5);
//    可变参数可以传递数组
    Integer[] arr = {1,2,3,4,5};
    Stream<Integer> stream2 = Stream.of(arr);

3.3 通过Arrays中得静态方法stream()获取数组流

IntStream stream = Arrays.stream(new int[] {1,2,3});

3.4 创建无限流(迭代、生成)

//迭代,需要传入一个起始值,然后传入一个一元操作
    Stream<Integer> stream = Stream.iterate(2, (x) -> x * 2);
//    生成无限产生对象
    Stream<Double> stream2 = Stream.generate(() -> Math.random());

四、Stream流中常用方法

4.1Stream流中API方法分为两类

(1)终结方法(及早求值):返回值类型不再是Stream接口自身类型的方法,因此不再支持链式调用

                                               及早求值得到的是最终结果而不是stream。

                                               count 和 forEach,max,min

(2)延迟方法(惰性求值):返回值类型仍然是Stream接口自身类型的方法,因此支持链式调用,除了终结方法为其与方法均为延迟方法。

                                            filter,map,flatMap

4.2 forEach

与for循环中的for-each不同

* void forEach(Consumer<? super T> action)
 * 该方法接收一个Consumer接口函数,会将每一个流元素交给函数进行处理
 * Consumer接口是一个消费型的函数式接口,可以传递lambda,其中有一个方法accept(s)进行消费数据

//获取Stream流
    Stream<String> stream = Stream.of("aa","cc","ads");
//    使用Stream中的方法forEach对Stream中的数据进行遍历
    stream.forEach(name -> System.out.println(name));

4.3 过滤 filter

用于对Stream中的数据进行过滤得到新的子集

//    创建一个Stream流
    Stream<String> stream = Stream.of("lily","linda","bom");
//    对流中的元素进行过滤,只要l
    Stream<String> stream2 = stream.filter(name -> name.startsWith("l"));
//    对stream2进行遍历
    stream2.forEach(name -> System.out.println(name));

4.4 映射 map

* <R> Stream<R> map(Function<? super T, ? extends R> mapper)
 * Function函数式接口中的R apply(T t).根据类型T的参数获取类型R的结果
 * 这种可以将一种T类型转换成R类型的转换动作,称之为映射

 Stream<String> stream = Stream.of("1","2","3");
//    使用map把String转换成Integer
    Stream<Integer> stream2 = stream.map(s -> Integer.parseInt(s));
//    遍历stream2
    stream2.forEach(i -> System.out.println(i));
 

4.5 统计个数: count

用于统计Stream流种元素的个数

是个终结方法

返回值是个long类型的整数

不能再继续调用Stream流中的其他方法

ArrayList<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(2);
   long count = list.stream().count();
   System.out.println(count);

4.6 取用前几个: limit

可以对流进行截取

是一个延迟方法

只是对流中的元素进行截取

返回的是新的流

可以继续调用Stream流中的方法

* Stream<T> limit(long maxSize)
* 参数是一个long型,如果集合当前长度大于参数增进行截取

String[] arr = {"as","asd","sdf"};
Stream<String> stream = Stream.of(arr);
Stream<String> stream2 = stream.limit(2);
stream2.forEach(name -> System.out.println(name));

运行结果:

4.7跳过前几个: skip

如果希望跳过恰鸡各元素,可以使用skip获取一个截取之后的新流

 * Stream<T> skip(long n)

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

String[] arr = {"as","asd","sdf"};
Stream<String> stream = Stream.of(arr);
Stream<String> stream2 = stream.skip(1);
stream2.forEach(name -> System.out.println(name));

运行结果:

4.8 组合 concat

将两个流合并成一个流

String[] arr = {"as","asd","sdf"};
Stream<String> stream = Stream.of(arr);
Stream<String> stream1 = Stream.of("lily","linda","bom");
Stream.concat(stream, stream1).forEach(name -> System.out.println(name));

4.9 并行(parallel)程序

List<String> list = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    long count = list.parallelStream().filter(s -> s.isEmpty()).count();
    System.out.println(count);

4.10 Collectors

Collectors类实现了很多归约操作,例如将流转换成集合和聚合元素。

//    collectors用于返回列表
    List<String> s = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    List<String> filtered = s.stream().filter(String -> !String.isEmpty()).collect(Collectors.toList());
    System.out.println("筛选列表" + filtered);
    
//   collectors用于返回字符串
   String mergedString = s.stream().filter(String -> !String.isEmpty()).collect(Collectors.joining(","));
    System.out.println("筛选列表" + mergedString);
    

4.11 统计

一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("列表中最大的数 : " + stats.getMax());
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum());
System.out.println("平均数 : " + stats.getAverage());

五、练习

 * 第一个list中筛选名字四三个长度,筛选后要前两个
 * 第二个list中筛选名字为l,要后两个
 * 根据姓名创建Person对象,存储到一个新集合中
 * 打印整个Person对象信息

 public static void main(String[] args) {
        List<String> list1 = new ArrayList<>();
         list1.add("lily");
         list1.add("linda");
         list1.add("bom");
         list1.add("aila");
         list1.add("comy");
//          第一个list中筛选名字四个长度,筛选后要前两个
       Stream<String> first = list1.stream().filter(name -> name.length() == 4).limit(2);
       List<String> list2 = new ArrayList<>();
       list2.add("lily");
       list2.add("linda");
       list2.add("bom");
       list2.add("lambda");
       list2.add("comy");
       Stream<String> second = list2.stream().filter(name -> name.startsWith("l")).skip(2);
//       根据姓名创建Person对象,存储到一个新集合中
//       打印整个Person对象信息
//       通过map映射成Person
       Stream.concat(first, second).map(name -> new Person(name)).forEach(p -> System.out.println(p));
       
         

运行结果:

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值