Catalog
  1. 1. Stream流,方法引用
    1. 1.1. Stream流
      1. 1.1.1. 代码展示
      2. 1.1.2. 引言
      3. 1.1.3. 获取流
      4. 1.1.4. 常用方法
    2. 1.2. 方法引用
      1. 1.2.1. 方法引用符
      2. 1.2.2. 方法引用的使用前提
Stream流,方法引用

Stream流,方法引用

Stream流

代码展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//对集合中的元素进行过滤,只要张开头的元素,存储到一个新的集合中
//对list集合进行过滤,只要姓名长度为3的人
//遍历list
list.stream()
.filter(name->name.startsWith("张"))
.filter(name->name.length()==3)
.forEach(System.out::println);
}

引言

就以上代码来看,如果使用传统的处理集合的方法,就需要创建两个新的集合,再对集合中的元素进行操作,最后在遍历集合输出结果,而Stream流的方式,显然更加简单优雅。

Stream是一个来自数据源的元素队列

  • 元素是特定类型的对象,形成一个队列。Java中的Stream并不会存储元素,而是按需计算。
  • 数据源流的来源,可以是集合,数组等。

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

  • Pipelining:中间操作都会返回流对象本身,这样多个操作可以串联成一个管道,如同流式风格。这样做可以对操作进行优化,比如延迟执行和短路。
  • 内部迭代:以前对集合遍历都是通过iterator或者增强for循环的方式,显式的在集合外部进行迭代,这叫做外部迭代。Stream提供了内部迭代的方式,流可以直接调用遍历方法。

当使用一个流的时候,通常包括三个基本步骤:获取一个数据源->数据转换->执行操作获取想要的结果。每次转换原油Stream对象不改变,返回一个新的Stream对象,这就允许其操作可以像链条一样排列,形成一个管道。

获取流

两种常用的方式:

  • 所有的Collection集合都可以通过stream默认方法获取流
  • stream接口的静态方法of可以获取数组对应的流
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    //把集合转换为Stream流
    List<String> list = new ArrayList<>();
    Stream<String> stream = list.stream();

    Set<String> set = new HashSet<>();
    Stream<String> stream1 = set.stream();

    //获取值,存储到一个Set集合中
    Map<String,String> map = new HashMap<>();
    Set<String> keySet = map.keySet();
    Stream<String> stream2 = keySet.stream();

    //获取值,存储到一个Collection集合中
    Collection<String> values = map.values();
    Stream<String> stream3 = values.stream();

    //获取键值对
    Set<Map.Entry<String,String>> entries = map.entrySet();
    Stream<Map.Entry<String, String>> stream4 = entries.stream();

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

    常用方法

  • 延迟方法:返回值类型仍然是Stream接口自身类型的方法,因此支持链式调用。
  • 终结方法:返回值类型不再是Stream接口自身类型的方法,因此不再支持蕾丝Stringbuilder那样的链式调用。

除了终结方法外,其余方法均为延迟方法。本小节之外的更多方法,请自行参考API文档。

逐一处理:forEach:

  • void forEach(Consumer<? super T> action);

作用:用来遍历流中的数据,是一个终结方法,遍历之后就不能继续调用Stream流中的其他方法。

过滤:filter
可以通过filter将一个流转换成另一个子集流。

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

映射:map:

可以将流中的元素映射到另一个流中,可以使用map方法。

1
2
3
4
Stream<String> stringStream = Stream.of("1", "2", "3", "4");
Stream<Integer> stream = stringStream.map((String s)->{
return Integer.parseInt(s);
});

统计个数:count

记录元素个数,返回的是long类型

  • long conut()

取用前几个:limit

1
Stream<T> limit(long maxSize);

跳过前几个:skip

如果跳过的个数大于长度,会返回一个长度为0的空流

1
Stream<T> skip(long n);

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

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

方法引用

在使用Lambda表达式的时候,我们实际上传递出去的代码就是一种解决方案:拿什么参数做什么操作。那么考虑一种情况,如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑?

方法引用符

双冒号::为引用运算符,而他所在的表达式被成为称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么可以通过双冒号来引用该方法作为Lambda的替代者。

1
.forEach(System.out::println);

方法引用的使用前提

  • 通过对象引用成员方法
  • 对象名是已经存在的,成员方法也是已经存在的
Author: zycode1561
Link: https://zycode1561.github.io/2020/01/23/Stream%E6%B5%81%EF%BC%8C%E6%96%B9%E6%B3%95%E5%BC%95%E7%94%A8/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
  • 支付宝

Comment