Java中的Stream,可以将其想象成一条流水线,你可以在这条流水线上进行各种处理。它可以帮助你处理集合中的数据,比如列表、数组等。
Stream的基本特性:
-
数据源: 你可以从集合(List、Set、Map等)、数组或者是其他数据源中创建Stream。
-
流水线操作: 你可以在Stream上执行各种操作,这些操作分为中间操作和终端操作。
-
中间操作: 这些操作可以链式调用,用于处理Stream中的数据,比如过滤、映射、排序等。这些操作不会立即执行,直到有终端操作出现(相当于它比较懒,只是先记下要执行什么操作,等到终端操作出现再一起做)。
-
终端操作: 当你想要从Stream中获取结果时,终端操作会触发Stream的执行。比如收集数据、计算、打印等。终端操作执行后,Stream将不可再用。
-
Stream的基本用法:
-
创建Stream: 你可以从各种数据源创建Stream。
- 从集合创建:
List.stream()
、Set.stream()
等。 - 从数组创建:
Arrays.stream(array)
。 - 使用Stream.of直接创建:
Stream.of(element1, element2, ...)
- 从集合创建:
-
中间操作: 对Stream进行处理和转换。
- 过滤:
filter(predicate)
:根据条件过滤元素。 - 映射:
map(mapper)
:对每个元素进行转换。 - 排序:
sorted()
:对元素进行排序。
- 过滤:
-
终端操作: 触发Stream执行并获得结果。
- 收集结果:
collect(Collectors.toList())
、collect(Collectors.toSet())
等:将Stream中的元素收集到集合中。 - 聚合操作:
reduce()
、count()
、max()
、min()
等:对Stream中的元素进行聚合或计算。 - 迭代操作:
forEach()
:对Stream中的每个元素执行特定操作。
- 收集结果:
具体的代码解释:
创建Stream:
从集合创建:
List<String> myList = Arrays.asList("apple", "banana", "orange");
Stream<String> streamFromList = myList.stream();
使用Stream.of创建:
Stream<String> streamOfValues = Stream.of("apple", "banana", "orange");
从数组创建:
int[] numbers = {1, 2, 3, 4, 5};
IntStream streamFromArray = Arrays.stream(numbers);
过滤:
过滤出以字母"a"开头的单词
Stream<String> filteredStream = streamFromList.filter(word -> word.startsWith("a"));
输出数据:
filteredStream.forEach(System.out::println);
把过滤后的数据输出到屏幕上
收集数据:
List<String> collectedList = uppercasedStream.collect(Collectors.toList());
把转换后的数据收集到一个List中
示例:将数字列表中的偶数取平方后收集到一个新的列表中
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evenSquaredNumbers = numbers.stream()
.filter(n -> n % 2 == 0) // 过滤偶数
.map(n -> n * n) // 对偶数取平方
.collect(Collectors.toList()); // 收集结果
System.out.println(evenSquaredNumbers); // 输出 [4, 16, 36, 64, 100]
这个例子中,我们通过Stream的中间操作筛选出偶数并对其进行平方处理,最后通过collect()
方法将结果收集到一个新的List中。
排序数据:
List<String> sortedList = words.stream()
.sorted()
.collect(Collectors.toList());
对单词进行排序,得到一个按照字典顺序排列的List
示例:找出所有以"a"开头的单词,转换为大写,并按字母顺序排序
List<String> words = Arrays.asList("apple", "banana", "orange");
List<String> result = words.stream()
.filter(word -> word.startsWith("a"))
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
System.out.println(result);
在这个例子中,我们从单词列表中创建了一个Stream
,然后通过filter
筛选出以"a"开头的单词,接着用map
将它们转换为大写形式,然后用sorted
按字母顺序排序,最后用collect
将结果收集到一个List中。最后,我们将结果输出到屏幕上。
Comparator自定义排序:
比如,我们想按照字符串长度来对一组单词进行排序:
List<String> words = Arrays.asList("banana", "apple", "orange", "grape");
List<String> sortedWords = words.stream()
.sorted(Comparator.comparing(String::length))
.collect(Collectors.toList());
System.out.println(sortedWords);
在这个例子中,我们使用sorted
方法的重载版本,传入了一个Comparator
对象,它通过comparing
方法指定了按照字符串长度进行比较。输出结果将是 ["apple", "grape", "banana", "orange"]
。
降序排序:
如果我们想要降序排序,只需在Comparator
上调用reversed
方法:
List<String> sortedWordsDesc = words.stream()
.sorted(Comparator.comparing(String::length).reversed())
.collect(Collectors.toList());
System.out.println(sortedWordsDesc);
这里,我们在comparing
方法后面调用了reversed
,表示按照字符串长度的降序排序。输出结果将是 ["orange", "banana", "grape", "apple"]
对
Comparator.comparingInt(String::length)的拆分理解:
-
Comparator.comparingInt: 这是一个静态方法,属于
Comparator
类。它接受一个函数作为参数,用于提取用于比较的关键值。在这里,我们使用String::length
,它是String
类中的实例方法length
的引用。 -
String::length: 这是一个方法引用,它是一种简化的Lambda表达式。在这里,它相当于
(String s) -> s.length()
,表示获取字符串的长度。
Stream提供了一种流畅、便捷的方式来处理数据,让代码更具可读性和简洁性。