首页 > 编程语言 >Java Stream流

Java Stream流

时间:2022-09-21 22:22:48浏览次数:92  
标签:Java Stream stream 元素 list add array

Java8 Stream流编程

Stream 使用一种类似于SQL语句从数据库查询数据的直观方式来提供对 Java 集合运算和表达的高阶抽象。得益于 Lambda 所带来的函数式编程,Stream API 可以极大的提高 Java 程序员的生产力。关于函数式编程可以查看我的另一篇博客 Java 函数式接口

什么是 Stream 流

A sequence of elements supporting sequential and parallel aggregate operations.

翻译过来就是一个支持串行和并行聚合操作的元素序列:

  • 序列中的元素是一个特定类型的对象,Stream 本身并不会存储任何元素,而是按需计算
  • 序列的来源可以是集合、数组、I/O channel等
  • 聚合操作是类型 SQL 语句的操作,如 fiter, map, distinct, sorted 等

获取 Stream 流

  • stream():创建串行流
  • parallelStream():创建并行流

Java 数组

// 基本类型数组,使用 Arrays.stream() 获取流,类似的还有 LongStream, DoubleStream
int[] nums = {1, 2, 3}
IntStream intStream = Arrays.stream(arr);

// 对象类型数组,使用 Stream.of() 获取流
String[] array = {"a", "b", "c"};
// Stream.of() 内部还是调用的 Arrays.stream(T[] values)
Stream<String> stream = Stream.of(array);

Java 集合

// 集合类型获取串行流
List<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.stream();

// 集合类型获取并行流
// 方法一:直接获取
// 方法二:从串行流转换
Stream<Integer> parallelStream = list.parallelStream();
Stream<Integer> parallelStream = list.stream().parallel();

Set<Integer> set = new HashSet<>();
Stream<Integer> stream2 = set.stream();

Stack<Integer> stack = new Stack<>();
Stream<Integer> stream3 = stack.stream();

Java Map

Map<String, String> map = new HashMap<>();
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
Stream<String> keyStream = map.keySet().stream();
Stream<String> valueStream = map.valueSet().stream();

Java Stream 的使用

数组元素求和

// 传统做法
int[] nums = {1, 2, 3, 4, 5};
int sum = 0;
for (int num : nums) {
  sum += nums;
}

// 使用 Stream 求和
int sum = Arrays.stream(nums).sum();

集合遍历过滤

List<String> list = new ArrayList<>();
list.add("ab");
list.add("abc");
list.add("aefg");
list.add("hijkl");

// 传统方法
List<String> startWithA = new ArrayList<>();
for (String temp : list) {
  if (temp.startsWith("a")) {
    startWithA.add(temp);
  }
}

List<String> longList = new ArrayList<>();
for (String temp : startWithA) {
  if (temp.length() >= 4) {
    longList.add(temp);
  }
}


// Stream 方法
List<String> filtered = list.stream().filter(s -> s.startsWith("a"))
                                     .filter(s -> s.length() >= 4)
                                     .collect(Collectors.toList());

Stream 风格可以使得 Java 代码干净、简洁,这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理。

从上面的例子可以看出 Stream 操作有以下两个特征:

  • 中间操作会返回流对象本身,多个操作可以串联成一个管道,如同流式风格
  • 传统集合遍历都是通过迭代器或者For-Each的方式在集合外部进行迭代,Stream 提供了内部迭代的方式,通过访问者模式实现

Java Stream 常用方法分析

filter() 方法

将 Stream 流转换成一个子集流。

/**
 * Returns a stream consisting of the elements of this stream 
 * that match the given predicate.
 */
Stream<T> filter(Predicate<? super T> predicate);

// Example
String[] array = {"a", "bc", "def", "ghij"};
Stream<String> stream = Stream.of(array);

// 子集流中包括元素 "def", "ghij"
Stream<String> subStream = stream.filter(s -> s.length() >= 3); 

map() 方法

将 Stream 流中的元素映射到另一个流中。

/**
 * Returns a stream consisting of the results of applying the given
 * function to the elements of this stream.
 */
<R> Stream<R> map(Function<? super T, ? extends R> mapper);

// Example
String[] array = {"a", "bc", "def", "ghij"};
Stream<String> stream = Stream.of(array);

// 流中包括array每个字符串的长度,{1, 2, 3, 4}
Stream<Integer> mapStream = stream.map(s -> s.length());

distinct() 方法

对 Stream 流中的元素做去重处理。

/**
 * Returns a stream consisting of the distinct elements (according to
 * {@link Object#equals(Object)}) of this stream.
 */
Stream<T> distinct();

// Example
String[] array = {"a", "bc", "def", "bc", "a"};
Stream<String> stream = Stream.of(array);

// "a", "bc" 是重复元素, distinct处理后流中只会保留一个
Stream<String> distinctStream = stream.distinct();

sorted() 方法

对 Stream 流中的元素排序。

/**
 * Returns a stream consisting of the elements of this stream, sorted
 * according to natural order.  If the elements of this stream are
 * not{@code Comparable}, a {@code java.lang.ClassCastException} may 
 * be thrown when the terminal operation is executed.
 */
Stream<T> sorted();

// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);

// 流中的元素按字典顺序升序排列
// {"a", "ab", "b", "c", "cc"}
Stream<String> sortedStream = stream.sorted();


/**
 * Returns a stream consisting of the elements of this stream, sorted
 * according to the provided {@code Comparator}.
 * 自定义排序规则
 */
Stream<T> sorted(Comparator<? super T> comparator);

// 流中的元素按长度升序排列
// {"a", "b", "c", "ab", "cc"}
Stream<String> sortedStream = stream.sorted((o1, o2) -> o1.length() - o2.length());

limit() 方法

截取流中的元素,取前 maxSize 个元素。

/**
 * Returns a stream consisting of the elements of this stream,
 * truncated to be no longer than {@code maxSize} in length. Stream<T> 
 * limit(long maxSize);
 */
Stream<T> limit(long maxSize);

// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);

// 截取流中前3个元素,{"a", "cc", "ab"}
Stream<String> limitStream = stream.limit(3);

skip() 方法

跳过前 n 个元素,如果原 Stream 流中元素个数小于 n,则返回一个空的 Stream 流。

 /**
  * Returns a stream consisting of the remaining elements of this 
  * stream after discarding the first {@code n} elements of the 
  * stream.
  * If this stream contains fewer than {@code n} elements then an
  * empty stream will be returned.
  */
Stream<T> skip(long n);

// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);

// 跳过流中前3个元素,返回 {"b", "c"}
Stream<String> limitStream = stream.skip(3);
// 跳过流中前5个元素,返回 {}
Stream<String> limitStream = stream.skip(3);

forEach() 方法

将每一个流元素交给 action 中的方法处理。

forEach 与 forEachOrdered

  • 串行流,两者的效果一致,都是对流中的元素顺序执行 action 中的操作
  • 并行流,forEach操作元素不一定按顺序执行,而forEachOrdered则保证元素按顺序执行
/**
 * Performs an action for each element of this stream.
 */
void forEach(Consumer<? super T> action);

/**
 * Performs an action for each element of this stream, in the 
 * encounter order of the stream if the stream has a defined 
 * encounter order.
 */
void forEachOrdered(Consumer<? super T> action);

// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);

// 顺序输出流中的元素,{"a", "cc", "ab", "b", "c"}
stream.forEach(s -> System.out.println(s));
stream.forEachOrdered(s -> System.out.println(s));

toArray() 方法

返回一个数组,包含 Stream 流中的元素。

/**
 * Returns an array containing the elements of this stream.
 */
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);

// 将原Stream流中的元素去重后转换为数组
String[] array2 = (String[])stream.distinct().toArray();

min(), max() 方法

分别返回 Stream 流中最小的元素,最大的元素。

/**
 * Returns the minimum element of this stream according to the 
 * provided.
 */
Optional<T> min(Comparator<? super T> comparator);

// Example
List<Integer> list = new ArrayList<>();

list.add(2);
list.add(4);
list.add(1);
list.add(3);
Optional<Integer> min = list.stream().min((o1, o2) -> o1 - o2);
Optional<Integer> max = list.stream().max((o1, o2) -> o1 - o2);

// 1, 4
System.out.println(min.get() + ", " + max.get());

count() 方法

返回 Stream 流中元素的个数。

/**
 * Returns the count of elements in this stream.
 */
long count();

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

list.add(2);
list.add(4);
list.add(1);
list.add(3);

// 4
long numbers = list.stream().count();

anyMatch() 方法

Stream 流中存在元素满足 predicate 中的约束,则返回 True

/**
 * Returns whether any elements of this stream match the provided
 * predicate.
 */
boolean anyMatch(Predicate<? super T> predicate);

// Example
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);

boolean flag1 = list.stream().anyMatch(num -> num > 2);    // True
boolean flag2 = list.stream().anyMatch(num -> num > 4);    // False

allMatch() 方法

Stream 流中所有元素满足 predicate 中的约束,则返回 True

/**
 * Returns whether all elements of this stream match the provided 
 * predicate.
 */
boolean allMatch(Predicate<? super T> predicate);

// Example
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);

boolean flag1 = list.stream().allMatch(num -> num > 0);    // True
boolean flag2 = list.stream().allMatch(num -> num > 2);    // False

concat() 方法

合并两个 Stream 流中的元素。

/**
 * Creates a lazily concatenated stream whose elements are all the
 * elements of the first stream followed by all the elements of the
 * second 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));
}

// Example
String[] s1 = {"a", "c", "e"};
String[] s2 = {"b", "d", "f"};

// {"a", "c", "e", "b", "d", "f"}
Stream.concat(Stream.of(s1), Stream.of(s2)).forEach(s -> System.out.println(s));

参考文章

[1] Java-Stream流详解

[2] Java 8 Stream 菜鸟教程

标签:Java,Stream,stream,元素,list,add,array
From: https://www.cnblogs.com/ylyzty/p/16717368.html

相关文章

  • javascript: 复制数组时的深拷贝及浅拷贝(chrome 105.0.5195.125)
    一,js代码:<html><head><metacharset="utf-8"/><title>测试</title></head><body><buttononclick="assignCopy()">无效:变量直接赋值</button><br/><br......
  • Javaweb学习笔记第十弹
    本章存在的意义,大概就是为了回顾一下被遗忘不久的html了HTML:超文本标记语言(不区分大小写,语法较为松散,但建议书写时规范一些)HTML标签由浏览器来解析标签展示图片具体详......
  • javaScript 字符串方法,字符串搜索,
     //这是字符串 能够使用单引号或双引号    varmko='helloworedw'    varqwe="hello worasd"    //new 一个字符串   ......
  • Day7 Javase抽象接口以及异常的捕获和抛出
    Day7面向对象编程抽象abstract修饰抽象类,如果修饰方法就是抽象方法。抽象方法可以写方法体,然后让继承抽象类的类去重写抽象方法。java的类是单继承的,但是接口可以实现......
  • JAVA多线程-学习笔记
    1.1概述程序:程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。进程(Porcess):是执行程序的一次执行过程,是一个动态的概念,是系统资源分配的单位。线......
  • OtherStream
    OtherStream一,标准的输入,输出流1.标准的输入、输出流1.1System.in:标准的输入流,默认从键盘输入System.out:标准的输出流,默认从控制台输出1.2System类的setIn(InputS......
  • Java: Immutable Patterns
     /***版权所有2022涂聚文有限公司*许可信息查看:*描述:*不变模式ImmutablePatterns*历史版本:JDK14.02*2022-09-12创建者geovindu*2022-09-1......
  • Java流程控制01(Scanner用法)
    使用next():packageScanner;importjava.util.Scanner;publicclassDemo01{publicstaticvoidmain(String[]args){//创建一个扫描器对象,用于接受......
  • Java map和flatmap
    importjava.lang.reflect.Array;importjava.util.ArrayList;importjava.util.List;importjava.util.Locale;publicclass_1{publicstaticvoidmain(Str......
  • JavaLearnDay03
    转义字符引用数据类型·特点:存储一个引用(内存地址)通过引用指向内存地址中的数据值·字符串类型:关键字:String作用:存储多个字符补充内容:在Java中所有整数默认为int......