Java基础——Stream类

文章目录

  • 1 概述
  • 2 获取Stream对象
  • 3 常用API
  • 4 收集Stream流
  • 5 总结

1 概述

Stream类用于简化集合和数组操作的API。
Stream类提供了很多可以简化集合操作的api,比如过滤元素
示例如下:
假如一个List集合中存储着字符串,从这些字符串中找到以“1”开头并长度为3的字符串加入一个新的List集合中。

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();

    list.add("123");
    list.add("145435");
    list.add("145");
    list.add("234");
    list.add("5435");
    list.add("189");

    ArrayList<String> newList = new ArrayList<>();
    for (String s : list) {
        if (s.startsWith("1") && s.length() == 3) {
            newList.add(s);
        }
    }
    System.out.println(newList);
}

使用stream可以简化上面的写法

public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<>();

    list.add("123");
    list.add("145435");
    list.add("145");
    list.add("234");
    list.add("5435");
    list.add("189");

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

    list.stream().filter(s -> s.startsWith("1")).filter(s -> s.length() == 3).forEach(s -> newList.add(s));
    System.out.println(newList);
}

Stream流其中的一些接口返回的还是Stream对象,可以支持链式编程。
通常使用步骤可以分为:

  • 获取集合和数组的Stream流

  • 放置元素

  • 使用Stream流的api方便操作元素
    Stream当中的方法可以分为:

  • 获取Stream流

  • 中间方法:返回的还是Stream对象

  • 终结方法:无返回,代表Stream使用结束

2 获取Stream对象

//集合
Collection<String> list = new ArrayList<>();
Stream<String> s = list.stream();
//Map
Map<String, Integer> map = new HashMap<>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
//数组
String[] strs = {"4324", "243324"};
Stream<String> strStream = Arrays.stream(strs);
Stream<String> strStream1 = Stream.of(strs);

Collection接口中提供了stream方法用于返回stream流

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

是一个默认方法。
Map中可以返回key、value和entry类型的stream流
数组返回stream流借助于Arrays工具类,其中Stream中的静态方法of也是借助于Arrays工具类返回Stream流

public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

3 常用API

先创建一个List集合

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

list.add("123");
list.add("145435");
list.add("145");
list.add("234");
list.add("5435");
list.add("189");
  • 过滤和遍历
//Stream filter(Predicate predicate);
//void forEach(Consumer action);
list.stream().filter(s -> s.startsWith("1")).forEach(s -> System.out.println(s));

filter返回一个stream对象,forEach返回空,用于遍历元素。
输出:

123
145435
145
189
  • 统计元素个数
//long count();
long size = list.stream().filter(s -> s.startsWith("1")).count();
System.out.println(size);

输出

4
  • 取前几个元素或跳过前几个元素
//Stream limit(long maxSize);
list.stream().filter(s -> s.startsWith("1")).limit(2).forEach(System.out::println);
//Stream skip(long n);
list.stream().filter(s -> s.startsWith("1")).skip(2).forEach(System.out::println);

输出

123
145435
145
189

这两个方法的参数都只能取大于等于0的值,否则会报异常。limit当值大于size时,取全部元素,skip当值大于size时,不返回任何元素。

  • 加工元素
// Stream map(Function mapper);
list.stream().map(s -> "map: " + s).forEach(System.out::println);

输出:

map: 123
map: 145435
map: 145
map: 234
map: 5435
map: 189

入参是一个函数式接口Function,重写apply方法,用于操作修改元素。
还可以构建对象

list.stream().map(s -> new Number(s)).forEach(System.out::println);

Number是一个类,包含了一个有参构造,可以通过map构造一个Number对象的stream流。

  • 合并流
Stream<String> s1 = list.stream().filter(s -> s.startsWith("1"));
Stream<String> s2 = Stream.of("213","231");
Stream<Object> s3 = Stream.concat(s1, s2);
s3.forEach(System.out::println);

concat是Stream接口中的一个静态方法。

public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
    Objects.requireNonNull(a);
    Objects.requireNonNull(b);

    @SuppressWarnings("unchecked")
    Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
            (Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
    Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
    return stream.onClose(Streams.composedClose(a, b));
}

接收的泛型必须是两个的公共父类
输出:

123
145435
145
189
213
231
  • 去除重复
list.stream().distinct().forEach(System.out::println);

去除重复的元素,依赖于hashCode方法和equals方法

4 收集Stream流

将Stream操作后的数据转回集合和数组中去

//收集到List集合中
Stream<String> s1 = list.stream().filter(s -> s.startsWith("1"));
List<String> newList = s1.collect(Collectors.toList());
//List newList1 = s1.toList(); //也是stream被收集过了,不能再使用
System.out.println(newList);
//收集到Set集合中
Set<String> newSet = s1.collect(Collectors.toSet()); //1
System.out.println(newSet);

注释1处报错
在这里插入图片描述
流只能收集一次,收集一次之后,就不能再使用了。

Stream<String> s1 = list.stream().filter(s -> s.startsWith("1"));
Object[] strs = s1.toArray();
System.out.println(Arrays.toString(strs));

转换成数组,就直接使用toArray方法,返回的是一个Object数组,因为Stream流中可以引入其他类型的元素
如果能够确定Stream中的元素都是同一种类型,则可以直接通过toArray的一个api去操作

String[] strs = s1.toArray(String[]::new);

提供一个构造,构造传入的是特定类型数组长度,数组长度会通过toArray传入。

5 总结

  • Stream流用于简化数组和集合的操作
  • 其中常用方法有filter过滤集合元素、forEach遍历集合元素、map加工集合元素、count统计元素个数、concat拼接Stream流、distinct去重等
  • Stream操作集合和数组元素之后需要转回集合或数组
  • 通过提供的toArraytoListcollect方法来完成收集转化

你可能感兴趣的:(#,Java基础知识,java,windows,python)