Java 8 流 API
Java Stream
是 Java 8 版本中加入的一个新概念,它允许我们对元素流执行函数式操作,比如集合上的 map-reduce 转换。
Java 增加了一个新的包 java.util.stream ,它由几个类、接口组成,用于执行基于流的操作。
Java 流是一个能够执行其元素内部操作的组件。例如,它可以自己迭代它的元素。
流操作分为中间操作和终端操作。流源可以是集合、数组、生成器函数或输入/输出通道。
中间操作是懒操作,返回新的流。例如,执行诸如filter()
的中间操作实际上并不执行任何过滤,而是创建一个新的流。
终端操作执行操作后终止流源管道。例如,Stream.forEach
或IntStream.sum
可以遍历流以产生结果。
河流的特征
本质上是功能性的
流本质上是功能性的,它允许我们执行功能性风格的操作。对流的操作会产生结果,但不会修改其源。例如,过滤从集合中获得的流会生成一个没有过滤元素的新流,而不是从源集合中移除元素。
寻懒
Stream 使用惰性加载来提高性能。我们可以在许多流操作中使用延迟加载,如过滤、映射或重复删除等。流中间操作总是懒惰的。
无储存
流不是存储元素的数据结构,但它通过计算操作的管道传递来自源(如集合、数组或生成器函数)的元素。
可能无界
虽然 Java 集合的大小是有限的,但是流不需要。limit(n)或 findFirst()等短路操作可以允许在有限时间内完成对无限流的计算。
消耗品
在流的生命周期中,流的元素只被访问一次。再次重用流引用不起作用。我们需要创建一个新的流来重新访问源的相同元素。
如何创建流?
在集合中,我们可以通过stream()
和parallelStream()
方法创建流,并通过Arrays.stream(Object[])
方法从数组中创建流。我们将在这里看到创建流的实际例子。
Java.util.stream 的接口
以下是 java.util.stream 包的接口。我们可以在各种编程场景中使用这些来获取流。
|
连接
|
描述
| | 基流〔t0〕 | 它是流的基本接口,流是支持顺序和并行聚合操作的元素序列。 | | 收集器 | 一种可变的约简操作,将输入元素累积到可变的结果容器中,在处理完所有输入元素后,可选地将累积的结果转换为最终表示。 | | 双流 | 支持顺序和并行聚合操作的原始双值元素序列。 | | DoubleStream。建设者 | 双流的可变生成器。 | | IntStream | 支持顺序和并行聚合操作的一系列原始 int 值元素。 | | IntStream(串流)。Builder(构建器) | IntStream 的可变生成器。 | | 软件复读机 | 支持顺序和并行聚合操作的原始长值元素序列。 | | LongStream。建设者 | 长流的可变构建器。 | | 流 | 支持顺序和并行聚合操作的元素序列。 | | 小溪。建筑商 | 流的可变构建器。 |
Java.util.stream 的类
以下是 java.util.stream 包的类。我们可以使用这些类来收集中间数据和操作流。
| 班级 | 描述 | | 收集者 | 实现各种有用的约简操作的收集器的实现,例如将元素累积到集合中,根据各种标准汇总元素等。 | | StreamSupport | 用于创建和操作流的低级实用方法。 |
举例时间:
让我们举一个从列表创建流的例子。在这里,我们将所有列表元素转换成小写,并使用forEach()
方法进行迭代。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class STDemo {
public static void main(String[] args){
List<String> fruits = new ArrayList<String>();
fruits.add("APPLE");
fruits.add("BANANA");
fruits.add("CHERRY");
Stream<String> stream = fruits.stream();
Stream<String> stringStream =
stream.map((value) -> { return value.toLowerCase(); });
stringStream.forEach(System.out::println);
}
}
苹果 香蕉 樱桃
示例:筛选列表元素
我们可以使用流来过滤集合元素。在这里,我们使用filter()
方法,并收集结果作为列表。filter()方法将 lambda 表达式作为参数。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class STDemo {
public static void main(String[] args){
List<Integer> numbers = new ArrayList<Integer>();
numbers.add(100);
numbers.add(110);
numbers.add(120);
numbers.add(150);
List<Integer> newlist =numbers.stream()
.filter(n->n>110)
.collect(Collectors.toList());
System.out.println(newlist);
}
}
【120,150】
示例:迭代元素
在流中遍历集合元素非常容易。我们只需要调用forEach()
方法,得到遍历的所有元素。看,我们在 forEach()方法中传递了一个方法引用来PrintStream
结果。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class STDemo {
public static void main(String[] args){
List<Integer> numbers = new ArrayList<Integer>();
numbers.add(100);
numbers.add(110);
numbers.add(120);
numbers.add(150);
Stream<Integer> stream = numbers.stream();
stream.forEach(System.out::println);
}
}
100 110 120 150
示例:最小值和最大值
如果我们想获得集合的最小值或最大值,那么通过使用流,我们可以很容易地做到这一点。这里,我们使用min()
和max()
方法从流中获取结果。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class STDemo {
public static void main(String[] args){
List<Integer> numbers = new ArrayList<Integer>();
numbers.add(100);
numbers.add(110);
numbers.add(120);
numbers.add(150);
Stream<Integer> stream = numbers.stream();
int max_val = stream.max((x,y)->x>y?1:-1).get();
System.out.println("Max Value : "+max_val);
int min_val = numbers.stream().min((x,y)->x<y?-1:1).get();
System.out.println("Min Value : "+min_val);
}
}
最大值:150 最小值:100
示例:使用 reduce()方法求和
reduce()
是一种将流中的元素简化为单个元素的方法,可用于获取所有元素的总和。见下面的例子。
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class STDemo {
public static void main(String[] args){
List<Integer> numbers = new ArrayList<Integer>();
numbers.add(100);
numbers.add(110);
numbers.add(120);
numbers.add(150);
System.out.println(numbers);
Stream<Integer> stream = numbers.stream();
Optional<Integer> sum = stream.reduce(Integer::sum);
System.out.println("Sum = "+sum.get());
}
}
【100,110,120,150】 总和= 480
示例:计算流元素
有一个count()
方法可以用来知道流中元素的数量。请看下面的例子。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class STDemo {
public static void main(String[] args){
List<Integer> numbers = new ArrayList<Integer>();
numbers.add(100);
numbers.add(110);
numbers.add(120);
numbers.add(150);
System.out.println(numbers);
Stream<Integer> stream = numbers.stream();
long count = stream.count();
System.out.println("Total Values = "+count);
}
}
【100,110,120,150】 总值= 4
示例:列表到集合转换
有时我们需要将流从一种类型转换成另一种类型,然后我们在 Collectors 类中有预定义的方法。例如,要将列表转换为集合,我们可以使用toSet()
方法。
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class STDemo {
public static void main(String[] args){
List<Integer> numbers = new ArrayList<Integer>();
numbers.add(100);
numbers.add(110);
numbers.add(120);
numbers.add(150);
numbers.add(110);
System.out.println(numbers);
Stream<Integer> stream = numbers.stream();
Set<Integer> set = stream.collect(Collectors.toSet());
System.out.println("Set Values = "+set);
}
}
【100,110,120,150,110】 设定值=【100,150,120,110】
示例:列表到数组的转换
这是从一种类型转换到另一种类型的另一个例子。这里,我们使用流的toArray()
方法将列表转换为数组。它返回一个对象数组。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class STDemo {
public static void main(String[] args){
List<Integer> numbers = new ArrayList<Integer>();
numbers.add(100);
numbers.add(110);
numbers.add(120);
numbers.add(150);
numbers.add(110);
System.out.println(numbers);
Stream<Integer> stream = numbers.stream();
Object[] intArray = stream.toArray();
for(Object element:intArray) {
System.out.print(element+" ");
}
}
}
【100、110、120、150、110】 100 110 120 150 110