一、创建
1、通过集合类创建
var list=Arrays.asList(1,2,3,4,5);
list.stream;
//Collection接口的实现类都可以使用流
//map则需要使用entrySet map.entrySet().stream();
2、通过Arrays.stream()创建
String[] array = {"apple", "banana", "orange"};
Stream<String> streamFromArray = Arrays.stream(array);
3、通过Stream.of静态方法创建
Stream<String> stream = Stream.of("apple", "banana", "orange");
4、使用生成器创建流
Stream<Integer> infiniteStream = Stream.generate(() -> 1);
//该流不会截至,因为闯入的supplier函数没有参数
//Supplier是一个函数接口,它不接受任何参数,但返回一个值
//生成的流是无限的 需要使用limit做数量限制
5、使用迭代器创建流
String<Integer> stream=Stream.iterate(0,n->n+2);
//创建的流也是无限的 同生成器一样
二、中间操作
过滤(filter)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
numbers.stream().filter(n->n%2==0).collect(Collectors.toList());
映射或称数据转换(map)
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
.map(String::Length)
.collect(Collectors.toList());
// Output: [2, 4, 6, 8, 10]
合并流(flatMap)
List<List<Integer>> nestedLists = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4));
List<Integer> flattenedList = nestedLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// Output: [1,2,3,4]
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(4, 5, 6);
list1.stream()
.flatMap(i -> list2.stream()
.map(j -> new int[]{i, j}))
.forEach(ints -> System.out.println(Arrays.toString(ints)));
}
// Outpout: [1,4] [1,5] [1,6] [2,4]......[3,6]
去重(distinct)
List<Integer> numbersWithDuplicates = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> distinctNumbers = numbersWithDuplicates.stream()
.distinct()
.collect(Collectors.toList());
// Output: [1, 2, 3, 4, 5]
排序(sort)
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6, 5);
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
// Output: [1, 1, 2, 3, 4, 5, 5, 6, 9]
对每个元素执行操作(peek)
//通常用于调试或记录流的中间状态
List<String> names = Arrays.asList("John", "Jane", "Doe");
List<String> processedNames = names.stream()
.peek(name -> System.out.println("Processing: " + name))
.map(String::toUpperCase)
.collect(Collectors.toList());
// Output:
// Processing: John
// Processing: Jane
// Processing: Doe
限制数量(limit,skip)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> limitedAndSkipped = numbers.stream()
.skip(3)
.limit(5)
.collect(Collectors.toList());
// Output: [4, 5, 6, 7, 8]
保留符合给定条件的元素(takeWhile)
// 保留符合给定条件的元素,一旦遇到不符合条件的元素就停止。
// dropWhile丢弃符合给定条件的元素,一旦遇到不符合条件的元素就保留之后的所有元素。
List<Integer> numbers = Arrays.asList(2, 4, 6, 1, 8, 10);
List<Integer> takenWhileEven = numbers.stream()
.takeWhile(n -> n % 2 == 0)
.collect(Collectors.toList());
// Output: [2, 4, 6]
List<Integer> droppedWhileEven = numbers.stream()
.dropWhile(n -> n % 2 == 0)
.collect(Collectors.toList());
// Output: [1, 8, 10]
三、终端操作
遍历 forEach(Consumer action)
List<String> names = Arrays.asList("John", "Jane", "Doe");
names.stream().forEach(System.out::println);
// Output:
// John
// Jane
// Doe
转为数组 toArray()
List<String> names = Arrays.asList("John", "Jane", "Doe");
String[] namesArray = names.stream().toArray(String[]::new);
收集 collect(Collector<T, A, R> collector)
List<String> names = Arrays.asList("John", "Jane", "Doe");
List<String> collectedNames = names.stream().collect(Collectors.toList());
Collectors
toList()
List<String> names = Arrays.asList("John", "Jane", "Doe");
List<String> collectedNames = names.stream().collect(Collectors.toList());
toSet()
List<String> names = Arrays.asList("John", "Jane", "Doe");
Set<String> collectedNames = names.stream().collect(Collectors.toSet());
toMap()
List<String> names = Arrays.asList("John", "Jane", "Doe");
Map<Integer, String> namesMap = names.stream()
.collect(Collectors.toMap(String::length, Function.identity()));
joining()
List<String> names = Arrays.asList("John", "Jane", "Doe");
String result = names.stream().collect(Collectors.joining(", "));
// Output: "John, Jane, Doe"
//还可以提供前后缀
String resultWithPrefixSuffix = names.stream().collect(Collectors.joining(", ", "[", "]"));
// Output: "[John, Jane, Doe]"
counting()
List<String> names = Arrays.asList("John", "Jane", "Doe");
long count = names.stream().collect(Collectors.counting());
// Output: 3
summarizingInt(), summarizingDouble(), summarizingLong()
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
IntSummaryStatistics stats = numbers.stream().collect(Collectors.summarizingInt(Integer::intValue));
int sum = stats.getSum(); // 15
double average = stats.getAverage(); // 3.0
int min = stats.getMin(); // 1
int max = stats.getMax(); // 5
groupingBy(classifier)
List<String> names = Arrays.asList("John", "Jane", "Doe");
Map<Integer, List<String>> groupedByLength = names.stream()
.collect(Collectors.groupingBy(String::length));
partitioningBy(predicate)
List<String> names = Arrays.asList("John", "Jane", "Doe");
Map<Boolean, List<String>> partitioned = names.stream()
.collect(Collectors.partitioningBy(name -> name.startsWith("J")));
mapping(mapper, downstream)
List<String> names = Arrays.asList("John", "Jane", "Doe");
Map<Integer, Set<String>> lengthToNames = names.stream()
.collect(Collectors.groupingBy(String::length, Collectors.toSet()));
reducing(identity, mapper, op)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.collect(Collectors.reducing(0, Integer::sum));
toCollection(supplier)
List<String> names = Arrays.asList("John", "Jane", "Doe");
TreeSet<String> treeSet = names.stream().collect(Collectors.toCollection(TreeSet::new));
collectingAndThen(collector, finisher)
List<String> names = Arrays.asList("John", "Jane", "Doe");
Set<String> resultSet = names.stream()
.collect(Collectors.collectingAndThen(Collectors.toSet(), HashSet::new));
groupingByConcurrent(classifier)
List<String> names = Arrays.asList("John", "Jane", "Doe");
Map<Integer, List<String>> groupedByLength = names.stream()
.collect(Collectors.groupingByConcurrent(String::length));
归约 reduce(BinaryOperator accumulator)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
//可以有初始值
int sumWithIdentity = numbers.stream().reduce(0, (a, b) -> a + b);
聚合 count()
List<String> names = Arrays.asList("John", "Jane", "Doe");
long count = names.stream().count();
// Output: 3
单一匹配 anyMatch(Predicate predicate)
全匹配 allMatch(Predicate predicate)
全排除 noneMatch(Predicate predicate)
//anyMatch 检查流中是否至少有一个元素满足给定的条件。
//allMatch 检查流中的所有元素是否都满足给定的条件。
//noneMatch 检查流中是否没有元素满足给定的条件
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean anyEven = numbers.stream().anyMatch(n -> n % 2 == 0); // true
boolean allOdd = numbers.stream().allMatch(n -> n % 2 != 0); // false
boolean noneGreaterThanTen = numbers.stream().noneMatch(n -> n > 10); // true
找第一个 findFirst()
找任意 findAny()
//findFirst 返回流中的第一个元素。
//findAny 返回流中的任意一个元素,适用于并行流
List<String> names = Arrays.asList("John", "Jane", "Doe");
Optional<String> firstElement = names.stream().findFirst();
Optional<String> anyElement = names.stream().findAny();
最小 min(Comparator comparator)
最大 max(Comparator comparator)
//min 返回流中的最小元素,需要提供一个比较器。
//max 返回流中的最大元素,同样需要提供一个比较器
List<Integer> numbers = Arrays.asList(1, 5, 3, 8, 2);
Optional<Integer> minValue = numbers.stream().min(Integer::compareTo);
Optional<Integer> maxValue = numbers.stream().max(Integer::compareTo);
四、自定义
Collector.of 方法允许创建自定义的 Collector。通过这个方法,可以定义如何累积元素、并行合并中间结果,以及最终合并的逻辑。
public static <T, R> Collector<T, ?, R> of(Supplier<R> supplier,
BiConsumer<R, T> accumulator,
BinaryOperator<R> combiner,
Function<A, R> finisher,
Collector.Characteristics... characteristics)
supplier 是一个提供容器的无参函数。
accumulator 是一个将元素积累到容器的函数。
combiner 是一个用于合并两个部分结果的函数。
Function<A, R> finisher 结束操作。
characteristics 是一组枚举值,用于定义收集器的特性,
例如 CONCURRENT、UNORDERED、IDENTITY_FINISH 等。
示例:
public static void main(String[] args) {
List<String> words = List.of("apple", "orange", "banana");
// 使用自定义收集器计算字符串总长度
int totalLength = words.stream()
.collect(joiningLength());
System.out.println("Total length: " + totalLength); // 输出:Total length: 18
}
// 创建一个自定义的收集器,计算字符串总长度
public static Collector<String, ?, Integer> joiningLength() {
return Collector.of(
() -> new int[]{0}, // 供应源,用于创建一个包含累积结果的数组
(arr, str) -> arr[0] += str.length(), // 累积器,将字符串长度累积到数组中
(arr1, arr2) -> {
arr1[0] += arr2[0]; // 组合器,将两个部分结果的数组合并
return arr1;
},
arr -> arr[0] // 结束操作,提取最终结果
);
}
五、常见函数接口
Consumer:
- 代表一个接受单一参数并且没有返回值的操作。在流中,它通常用于对每个元素执行某个操作。
Consumer<String> printUpperCase = str -> System.out.println(str.toUpperCase());
Supplier:
- 代表一个不接受参数但返回结果的操作。在流中,它通常用于生成元素。
Supplier<String> helloSupplier = () -> "Hello, World!";
Function<T, R>:
- 代表一个接受一个参数并返回结果的函数。在流中,它通常用于对每个元素进行转换。
Function<String, Integer> strLengthFunction = str -> str.length();
Predicate:
- 代表一个接受一个参数并返回布尔值的断言。在流中,它通常用于筛选元素。
Predicate<Integer> isEven = num -> num % 2 == 0;
UnaryOperator:
- 代表一个接受和返回相同类型的操作。在流中,它通常用于对每个元素进行原位修改。
UnaryOperator<String> toUpperCaseOperator = str -> str.toUpperCase();
BinaryOperator:
- 代表一个接受两个相同类型参数并返回结果的操作。在流中,它通常用于对两个元素进行组合。
BinaryOperator<Integer> sumOperator = (num1, num2) -> num1 + num2;