stream是什么
Stream就像一条数据流,你可以把它看作是一系列元素的通道,这些元素可以是集合中的数据。使用Stream,你可以通过一系列的操作来处理这些数据,而不必显式地使用传统的循环和条件语句。Stream提供了一种更简洁、更易读的方法来对数据进行操作,尤其是对于集合(比如List、Set、Map等)中的元素。
Java Stream的特点
- 惰性求值: stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
- 函数式编程: Stream 提供了丰富的函数式编程操作,如 map、filter、reduce 等,使得对集合的处理更加灵活和表达力更强。
- 不改变原始数据: Stream 操作不会改变原始数据,而是返回一个新的 Stream。这种非破坏性的操作使得可以轻松地组合和复用操作。
流的操作种类
流的种类分为两种,元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果。
中间操作
中间操作是对流进行处理和转换的操作,它们不会触发实际的计算,而是返回一个新的 Stream。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。而是在终端操作开始的时候才真正开始执行。
通俗的解释是中间操作就像是对一条河流进行不同的处理,但并没有真正触发水流的运动,是工作前的准备,你可以在河流中设置一个过滤器,只允许通过的鱼有特定颜色。这只是一种设定,但并没有让鱼开始移动。这就是中间操作的作用。
终端操作
终端操作是对流进行最终处理的操作,它们会触发对流的遍历和计算,并生成一个结果。终端操作是流的最后一步,一旦触发,就无法再对同一个流进行其他操作。
通俗的解释是你可以把终端操作看作是在河流中放一个桶,捞起鱼,然后数一数。这个过程是真正触发了对水流的操作,得到了一个最终的结果,即桶中的鱼的数量。
stream的使用
中间操作的使用
filter(): 根据给定的条件过滤流中的元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> newNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
System.out.println(newNumbers);
//输出 [2、4、6]
map(): 将流中的每个元素映射为另一个元素。
List<String> words = Arrays.asList("apple","banana");
List<String> upperCaseWords = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(upperCaseWords); // 输出: [APPLE, BANANA]
distinct() 去除流中的重复元素。
List<String> myList = Arrays.asList("apple", "banana", "apple");
List<String> uniqueList = myList.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(uniqueList);
// ["apple", "banana"]
limit(long maxSize) 截取元素
List<String> myList = Arrays.asList("apple", "banana", "apple");
List<String> limitedList = myList.stream()
.limit(1)
.collect(Collectors.toList());
System.out.println(limitedList);
// ["apple"]
sorted() 将流中的元素按照自然排序方式进行排序。
List<Integer> numbers = List.of(5, 2, 8, 1, 6, 3, 7, 4);
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNumbers);
// [1, 2, 3, 4, 5, 6, 7, 8]
skip():和limit()相反,将前几个元素跳过(取出)再返回一个流,
List<String> myList = Arrays.asList("apple", "banana", "apple");
List<String> skipList = myList.stream()
.skip(1)
.collect(Collectors.toList());
System.out.println(skipList);
// ["banana", "apple"]
flatMap() 流中的每个元素都放到一个流中,最后将所有的流合并成一个新流
List<String> words = Arrays.asList("hello", "world");
List<String> uniqueCharacters = words.stream()
.flatMap(s -> Arrays.stream(s.split("")))
.distinct()
.collect(Collectors.toList());
System.out.println(uniqueCharacters);
// [h, e, l, o, w, r, d]
终端操作的使用
forEach() 对流中的每个元素执行指定的操作
List<String> myList = Arrays.asList("apple", "banana", "orange");
myList.stream().forEach(System.out::println);
// apple banana orange
collect() 将流元素收集到一个容器中,比如List,Set,Map。
List<String> myList = Arrays.asList("apple", "banana", "orange");
List<String> collectedList = myList.stream().collect(Collectors.toList());
Set<String> set = myList.stream().collect(Collectors.toSet());
Map<String, String> map = myList.stream().collect(Collectors.toMap(k -> k, v -> v));
System.out.println(collectedList);
// [apple, banana, orange]
System.out.println(set);
// [banana, orange, apple]
System.out.println(map);
// {banana=banana, orange=orange, apple=apple}
count()返回流中元素的数量
List<String> myList = Arrays.asList("apple", "banana", "orange");
long count = myList.stream().count();
System.out.println(count); // 3
reduce()对流中的元素进行归约操作
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Integer i = numbers.stream().reduce((a, b) -> a + b).get();
System.out.println(i); // 15
anyMatch()判断流中是否有任一元素匹配给定条件
List<String> myList = Arrays.asList("apple", "banana", "orange");
boolean anyMatch = myList.stream().anyMatch(s -> s.startsWith("a"));
System.out.println(anyMatch); // true
allMatch()判断流中是否所有元素都匹配给定条件
List<String> myList = Arrays.asList("apple", "banana", "orange");
boolean allMatch = myList.stream().allMatch(s -> s.length() > 3);
System.out.println(allMatch); // true
noneMatch()判断流中是否没有任何元素匹配给定条件
List<String> myList = Arrays.asList("apple", "banana", "orange");
boolean noneMatch = myList.stream().noneMatch(s -> s.contains("x"));
System.out.println(noneMatch); // true
findAny()返回流中的任意元素和findFirst()返回流中的第一个元素
List<String> myList = Arrays.asList("apple", "banana", "orange");
Optional<String> findAny = myList.stream().findAny();
Optional<String> first = myList.stream().findFirst();
System.out.println(findAny); // 可能是其中任何值
System.out.println(first); // Optional[apple]
min() 和 max() 返回流中的最小或最大元素。
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6);
Integer min = numbers.stream().min(Comparator.naturalOrder()).get(); Integer max = numbers.stream().max(Comparator.naturalOrder()).get();
System.out.println(min); // 1
System.out.println(max); // 9
groupingBy() 给定条件进行分组
List<String> myList = Arrays.asList("apple", "banana", "orange");
Map<Integer, List<String>> groupedByLength = myList.stream()
.collect(Collectors.groupingBy(String::length));
groupedByLength.forEach((length, strings) -> {
System.out.println("Length " + length + ": " + strings);
});
// Length 5: [apple]
// Length 6: [banana, orange]
上面列举了一些关于stream的常见用法
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。