java构建Stream流的多种方式总结
Java 8引入了Stream流作为一项新的特性,它是用来处理集合数据的一种函数式编程方式。Stream流提供了一种更简洁、高效和易于理解的方法来操作集合数据,同时也能够实现并行处理,以提高性能。
以下是Stream流的一些重要特征和用法:
- 流的创建:可以从集合、数组、I/O通道等多种数据源创建Stream流。例如,使用
Collection.stream()
方法可以将集合转换为流,使用Arrays.stream()
可以将数组转换为流。 - 中间操作:Stream流支持各种中间操作,这些操作允许对流中的元素进行过滤、映射、排序等操作,而不会修改原始数据。一些常见的中间操作包括
filter
(过滤元素)、map
(映射元素)、sorted
(排序元素)等。 - 终端操作:终端操作是对流进行最终操作,它们触发实际的计算并生成结果。一些常见的终端操作包括
forEach
(遍历元素并执行操作)、collect
(将流中的元素收集到一个集合中)、count
(计算元素个数)等。 - 延迟执行:Stream操作是延迟执行的,这意味着中间操作可以在不实际计算的情况下链接在一起。只有在调用终端操作时,才会触发流的处理。
- 并行处理:Stream流支持并行处理,通过使用
parallelStream()
方法,可以轻松地将流的处理分布到多个处理器核心上,以提高性能。 - 函数式编程风格:Stream流鼓励使用函数式编程风格,其中操作是以lambda表达式的形式传递的,使代码更具表达力和简洁。
以下是一个示例,演示了如何使用Stream流来操作一个集合:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int sum = numbers.stream() .filter(n -> n % 2 == 0) // 过滤偶数 .map(n -> n * 2) // 将偶数翻倍 .reduce(0, Integer::sum); // 求和 System.out.println("偶数的翻倍之和为: " + sum);
这只是Stream流的一个简单示例,它展示了Stream流的一些常见操作,如过滤、映射和汇总。通过Stream流,可以以更简洁和可读的方式处理集合数据,减少了样板代码,提高了代码质量和可维护性。下面我们将对构建流的多种方式多种方式展开做一个详细阐述。
1.从集合创建流
从集合创建Stream流非常简单,可以使用集合类的stream()
方法来获取一个Stream对象。下面我将展示如何从集合创建Stream,并结合实际应用提供两个代码示例。
示例1:从List创建Stream
import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; public class StreamCreationExample { public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("Alice"); names.add("Bob"); names.add("Charlie"); names.add("David"); names.add("Eve"); // 创建一个Stream流 Stream<String> nameStream = names.stream(); // 使用Stream流进行操作 nameStream .filter(name -> name.startsWith("A")) .forEach(System.out::println); } }
这个示例中,我们首先创建了一个包含一些姓名的List集合,然后使用names.stream()
方法创建了一个Stream流。接着,我们使用filter
中间操作筛选出以"A"开头的姓名,并使用forEach
终端操作打印输出结果。
示例2:从Map创建Stream
import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; public class StreamCreationFromMapExample { public static void main(String[] args) { Map<Integer, String> studentMap = new HashMap<>(); studentMap.put(1, "Alice"); studentMap.put(2, "Bob"); studentMap.put(3, "Charlie"); studentMap.put(4, "David"); studentMap.put(5, "Eve"); // 从Map的键集合创建Stream Stream<Integer> studentIdsStream = studentMap.keySet().stream(); // 使用Stream流进行操作 studentIdsStream .filter(id -> id % 2 == 0) .forEach(id -> System.out.println(id + ": " + studentMap.get(id))); } }
这个示例中,我们创建了一个包含学生ID和姓名的Map,然后使用studentMap.keySet().stream()
方法从Map的键集合创建了一个Stream流。接着,我们使用filter
中间操作筛选出偶数的学生ID,并使用forEach
终端操作打印出相应的学生信息。
2.从数组创建流
从数组创建Stream流也非常简单,Java 8 提供了Arrays.stream()
方法,它允许将一个数组转换为一个Stream流。下面我将详细介绍如何从数组创建Stream,并提供两个代码示例。
示例1:从整数数组创建Stream
import java.util.Arrays; import java.util.stream.IntStream; public class StreamCreationFromArrayExample { public static void main(String[] args) { int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 从整数数组创建IntStream IntStream numberStream = Arrays.stream(numbers); // 使用Stream流进行操作 int sum = numberStream .filter(n -> n % 2 == 0) .map(n -> n * 2) .sum(); System.out.println("偶数的翻倍之和为: " + sum); } }
在这个示例中,我们首先创建了一个整数数组 numbers
,然后使用 Arrays.stream(numbers)
方法将它转换为一个 IntStream
流。接着,我们使用该流进行一系列操作,包括筛选出偶数并将其翻倍,最后计算它们的总和。
示例2:从字符串数组创建Stream
import java.util.Arrays; import java.util.stream.Stream; public class StreamCreationFromArrayExample { public static void main(String[] args) { String[] words = {"apple", "banana", "cherry", "date", "elderberry"}; // 从字符串数组创建Stream Stream<String> wordStream = Arrays.stream(words); // 使用Stream流进行操作 wordStream .filter(word -> word.startsWith("b")) .map(String::toUpperCase) .forEach(System.out::println); } }
在这个示例中,我们创建了一个字符串数组 words
,然后使用 Arrays.stream(words)
方法将它转换为一个 Stream
流。接着,我们使用流进行操作,包括筛选出以字母 "b" 开头的单词,并将它们转换为大写形式后打印输出。
3.静态工厂方法
Java 8也引入了一些静态工厂方法来创建Stream流,这些方法使得创建Stream流变得更加简便和灵活。下面我将详细介绍这些静态工厂方法,并提供两个代码示例。
静态工厂方法创建Stream
Stream.of(T... values)
:通过将一个可变参数的元素列表传递给Stream.of
方法来创建一个包含这些元素的Stream流。这对于创建具有少量元素的流非常方便。Stream.empty()
:使用Stream.empty()
方法创建一个空的Stream流。Stream.generate(Supplier<T> s)
:通过提供一个Supplier
函数来创建一个无限大小的Stream流,该函数会生成元素。通常,需要使用limit
操作限制生成的元素数量。Stream.iterate(T seed, UnaryOperator<T> f)
:通过提供初始值(seed)和一个一元操作函数(UnaryOperator)来创建一个包含无限序列的Stream流。例如,可以使用Stream.iterate(0, n -> n + 1)
来创建一个自然数序列的Stream流。
示例1:使用Stream.of创建Stream
import java.util.stream.Stream; public class StreamFactoryExample { public static void main(String[] args) { // 使用Stream.of创建Stream流 Stream<String> stream = Stream.of("Apple", "Banana", "Cherry", "Date"); // 打印Stream中的元素 stream.forEach(System.out::println); } }
这个示例使用Stream.of
静态工厂方法创建了一个包含水果名称的Stream流,并使用forEach
终端操作打印出每个水果的名称。
示例2:使用Stream.generate创建Stream
import java.util.Random; import java.util.stream.Stream; public class StreamGenerateExample { public static void main(String[] args) { // 使用Stream.generate创建随机整数流 Stream<Integer> randomIntStream = Stream.generate(() -> new Random().nextInt(100)); // 限制流的元素数量,然后打印 randomIntStream .limit(10) .forEach(System.out::println); } }
在这个示例中,我们使用Stream.generate
静态工厂方法创建了一个包含随机整数的Stream流。然后,我们使用limit
操作限制了流中元素的数量,最后打印出了生成的随机整数。
这些静态工厂方法为创建不同类型的Stream提供了便捷的途径,使流的创建更加灵活和便捷。
4.使用 Stream.Builder
Stream.Builder
是Java 8引入的用于构建流的一种方式。它允许逐个添加元素到流中,并最终构建一个Stream对象。这对于在迭代或生成元素的过程中构建流非常有用。
下面是如何使用Stream.Builder
创建流的详细介绍,并提供两个代码示例。
使用Stream.Builder创建流的步骤
- 创建Stream.Builder对象:首先,需要创建一个
Stream.Builder
对象。 - 添加元素:然后,使用
Stream.Builder
的add
方法逐个添加元素到流中。 - 构建流:一旦添加了所有元素,可以调用
Stream.Builder
的build
方法来构建Stream对象。
示例1:使用Stream.Builder创建流并过滤奇数
import java.util.stream.Stream; public class StreamBuilderExample { public static void main(String[] args) { Stream.Builder<Integer> builder = Stream.builder(); // 添加元素到Stream for (int i = 1; i <= 10; i++) { builder.accept(i); } // 构建Stream Stream<Integer> numberStream = builder.build(); // 使用Stream操作 numberStream .filter(n -> n % 2 == 0) // 过滤偶数 .forEach(System.out::println); } }
在这个示例中,我们首先创建了一个Stream.Builder
对象,然后使用accept
方法逐个添加1到10的整数到流中,最后使用filter
中间操作筛选出偶数并使用forEach
终端操作打印出结果。
示例2:使用Stream.Builder生成斐波那契数列
import java.util.stream.Stream; public class FibonacciStreamExample { public static void main(String[] args) { Stream.Builder<Long> builder = Stream.builder(); long a = 0, b = 1; int count = 10; for (int i = 0; i < count; i++) { builder.accept(a); long next = a + b; a = b; b = next; } Stream<Long> fibonacciStream = builder.build(); fibonacciStream.forEach(System.out::println); } }
在这个示例中,我们使用Stream.Builder
生成斐波那契数列的前10个数字。我们首先创建一个Stream.Builder
对象,然后使用循环逐个添加斐波那契数列的元素,最后使用forEach
终端操作打印出结果。
Stream.Builder
适用于需要逐个生成元素并构建流的情况,使代码更加清晰和灵活。
5. 从文件创建流
在Java中,可以从文件创建Stream流以便进行文件的读取和处理。通常,可以使用java.nio.file
包中的类来实现这一目的。以下是如何从文件创建流的方法以及两个代码示例:
方法1:使用Files.lines方法创建文本文件的流
Files.lines
方法允许创建一个包含文件内容的Stream<String>
,适用于文本文件的逐行读取。该方法接受文件路径作为参数,并返回一个Stream
对象。
下面是一个示例:
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.stream.Stream; public class FileToStreamExample { public static void main(String[] args) { String filePath = "sample.txt"; // 文件路径 try (Stream<String> lines = Files.lines(Paths.get(filePath))) { lines.forEach(System.out::println); // 逐行打印文件内容 } catch (IOException e) { e.printStackTrace(); } } }
在这个示例中,我们使用Files.lines
方法打开名为"sample.txt"的文本文件,并将其内容逐行打印到控制台。
方法2:使用Files.newInputStream方法创建二进制文件的流
如果要处理二进制文件,例如图像或音频文件,可以使用Files.newInputStream
方法创建一个InputStream
,然后将其转换为Stream
。下面是一个示例:
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.stream.Stream; public class BinaryFileToStreamExample { public static void main(String[] args) { String filePath = "image.jpg"; // 二进制文件路径 try { Path path = Paths.get(filePath); Stream<Byte> byteStream = Files.newInputStream(path) .map(b -> (byte) b); byteStream.forEach(System.out::println); // 逐字节打印二进制文件内容 } catch (IOException e) { e.printStackTrace(); } } }
在这个示例中,我们使用Files.newInputStream
方法创建一个输入流,然后将其映射为Stream<Byte>
,并最终逐字节打印二进制文件的内容。
无论是文本文件还是二进制文件,从文件创建Stream流都是非常有用的,它使文件的读取和处理变得更加方便和灵活。在处理文件时,不要忘记适当地处理可能出现的IOException
异常。
以上就是java构建Stream流的多种方式总结的详细内容,更多关于java构建Stream流的资料请关注脚本之家其它相关文章!
相关文章
Spring Boot利用Docker快速部署项目的完整步骤
这篇文章主要给大家介绍了关于Spring Boot利用Docker快速部署项目的完整步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧2019-07-07Java中双重检查锁(double checked locking)的正确实现
双重检查锁(Double-Check Locking),顾名思义,通过两次检查,并基于加锁机制,实现某个功能,下面这篇文章主要给大家介绍了关于Java中双重检查锁(double checked locking)的相关资料,需要的朋友可以参考下2021-09-09Java Lambda表达式与匿名内部类的联系和区别实例分析
这篇文章主要介绍了Java Lambda表达式与匿名内部类的联系和区别,结合实例形式分析了Java Lambda表达式与匿名内部类功能、用法、区别及操作注意事项,需要的朋友可以参考下2019-10-10
最新评论