Stream 流用法详解
共计 5918 个字符,预计需要花费 15 分钟才能阅读完成。
简介
Stream 是 Java 8 引入的一个功能强大的流式处理 API。它允许我们以声明性的方式操作集合(数组、集合等)的元素。通过使用 Stream,我们可以将多个操作连接起来,形成一个流水线,从而简化代码并提高可读性。
Stream 类中包含的方法,可以进行数据筛选、转换、排序、去重、限制、跳过、归约、统计、匹配、查找和遍历等操作。
数据筛选和转换:
-
filter(Predicate<T> predicate)
:根据指定条件过滤流中的元素。 -
map(Function<T, R> mapper)
:对流中的元素进行映射操作,转换为另一种类型。 -
flatMap(Function<T, Stream<R>> mapper)
:对流中的元素进行映射操作,将每个元素映射为一个流,并将所有流的元素合并成一个流。
数据排序和去重:
-
sorted()
:对流中的元素进行排序操作。 -
distinct()
:去除流中的重复元素。
数据归约和统计:
-
count()
:返回流中的元素数量。 -
reduce(BinaryOperator<T> accumulator)
:对流中的元素进行归约操作,得到一个最终结果。 -
collect(Collector<T, A, R> collector)
:将流中的元素收集到一个集合或其他数据结构中。
数据匹配和查找:
-
max(Comparator<T> comparator)
:返回流中的最大元素。 -
min(Comparator<T> comparator)
:返回流中的最小元素。 -
findFirst()
:返回流中的第一个元素。 -
findAny()
:返回流中的任意一个元素。 -
anyMatch(Predicate<T> predicate)
:检查流中是否存在满足条件的元素。 -
allMatch(Predicate<T> predicate)
:检查流中的所有元素是否都满足条件。 -
noneMatch(Predicate<T> predicate)
:检查流中是否没有任何元素满足条件。
数据限制和跳过:
-
limit(long maxSize)
:限制流中元素的数量。 -
skip(long n)
:跳过流中的前 n 个元素。
其他方法:
-
forEach(Consumer<T> action)
:对流中的每个元素执行指定的操作。
使用
1. 数据筛选和转换
数据的筛选和转换用得最多的当属 filter 和 map 方法。
1.1 filter
根据指定的条件过滤流中的元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(evenNumbers); // 输出结果:[2, 4, 6]
1.2 map
对流中的元素进行映射操作,将其转换为另一种类型。
List<String> names = Arrays.asList("John", "Jane", "Tom");
List<Integer> nameLengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println(nameLengths); // 输出结果:[4, 4, 3]
2. 数据排序和去重
数据的排序和去重用得也是比较多的方法。
2.1 sorted
对流中的元素进行排序操作。
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 6);
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNumbers);v // 输出结果:[1, 2, 5, 6, 8]
2.2 distinct
去除流中重复的元素。
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4, 5);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(distinctNumbers); // 输出结果:[1, 2, 3, 4, 5]
3. 数据归约和统计
3.1 count
返回流中的元素数量。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
long count = numbers.stream()
.count();
System.out.println(count); // 输出结果:5
3.2 reduce
对流中的元素进行归约操作,将流中的元素通过指定的操作进行组合,得到一个最终结果。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream()
.reduce((a, b) -> a + b);
System.out.println(sum.orElse(0)); // 输出结果:15
3.3 collect
用于将流中的元素收集到一个集合或其他数据结构中。
将流元素收集到 List 中
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> collectedList = numbers.stream()
.collect(Collectors.toList());
System.out.println(collectedList);
将流元素收集到 Set 中
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4, 5);
Set<Integer> collectedSet = numbers.stream()
.collect(Collectors.toSet());
System.out.println(collectedSet);
将流元素收集到 Map 中
List<String> names = Arrays.asList("John", "Jane", "Tom");
Map<String, Integer> nameLengthMap = names.stream()
.collect(Collectors.toMap(
name -> name,
name -> name.length()
));
System.out.println(nameLengthMap); // 输出结果:{John=4, Jane=4, Tom=3}
根据某个属性对流中的元素进行分组
Person 类
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
可以根据年龄对 Person 对象进行分组:
List<Person> persons = Arrays.asList(
new Person("John", 25),
new Person("Jane", 30),
new Person("Tom", 22),
new Person("Alice", 30)
);
Map<Integer, List<Person>> ageGroupMap = persons.stream()
.collect(Collectors.groupingBy(Person::getAge));
System.out.println(ageGroupMap); // 输出结果:{22=[Person{name='Tom', age=22}], 25=[Person{name='John', age=25}], 30=[Person{name='Jane', age=30}, Person{name='Alice', age=30}]}
将流元素收集到自定义的容器中
自定义的容器类 PersonContainer
public class PersonContainer {
private List<Person> persons = new ArrayList<>();
public void addPerson(Person person) {
persons.add(person);
}
public List<Person> getPersons() {
return persons;
}
}
示例代码:
List<Person> persons = Arrays.asList(
new Person("John", 25),
new Person("Jane", 30),
new Person("Tom", 22)
);
PersonContainer container = persons.stream()
.collect(
PersonContainer::new,
PersonContainer::addPerson,
PersonContainer::addPerson
);
List<Person> collectedPersons = container.getPersons();
System.out.println(collectedPersons); // 输出结果:[Person{name='John', age=25}, Person{name='Jane', age=30}, Person{name='Tom', age=22}]
4. 数据匹配和查找
4.1 max
返回流中的最大的元素,返回是一个 Optional 类。
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 6);
Optional<Integer> maxNumber = numbers.stream()
.max(Integer::compareTo);
System.out.println(maxNumber.orElse(0)); // 输出 8
4.2 min
返回流中的最小的元素,返回是一个 Optional 类。
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 6);
Optional<Integer> minNumber = numbers.stream()
.min(Integer::compareTo);
System.out.println(minNumber.orElse(0)); // 输出 1
4.3 findFirst
返回流中的第一个元素(按照流的遍历顺序),返回是一个 Optional 类。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstNumber = numbers.stream()
.findFirst();
System.out.println(firstNumber.orElse(0)); // 输出 1
4.4 findAny
返回流中的任意一个元素,返回是一个 Optional 类。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> anyNumber = numbers.stream()
.findAny();
System.out.println(anyNumber.orElse(0)); // 输出结果:1(可能的结果因为随机性而有所不同)
4.5 anyMatch
检查流中是否存在满足给定条件的元素,返回是一个布尔值。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEvenNumber = numbers.stream()
.anyMatch(n -> n % 2 == 0);
System.out.println(hasEvenNumber); // 输出结果:true
4.6 anyMatch
检查流中的所有元素是否都满足给定条件,返回是一个布尔值。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allEvenNumbers = numbers.stream()
.allMatch(n -> n % 2 == 0);
System.out.println(allEvenNumbers); // 输出结果:false
4.7 noneMatch
检查流中是否没有任何元素满足给定条件。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean noNegativeNumbers = numbers.stream()
.noneMatch(n -> n < 0);
System.out.println(noNegativeNumbers); // 输出结果:true
5. 数据限制和跳过
5.1 limit
限制流中元素的数量。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream()
.limit(3)
.collect(Collectors.toList());
System.out.println(limitedNumbers); // 输出结果:[1, 2, 3]
5.2 skip
跳过流中的前 n 个元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream()
.skip(2)
.collect(Collectors.toList());
System.out.println(skippedNumbers);
6. 其他方法
6.1 forEach
对流中的每个元素执行指定的操作。
List<String> names = Arrays.asList("John", "Jane", "Tom");
names.stream()
.forEach(System.out::println);
提醒:本文发布于494天前,文中所关联的信息可能已发生改变,请知悉!
Tips:清朝云网络工作室