1. 概述
Java Stream API 是 Java 8 及以上版本中提供的一种新特性,它支持对集合(Collections)进行声明式的操作。Stream API 可以用于执行复杂的数据转换操作,并支持并行处理。
2. Steam操作
中间操作(Intermediate operations)
中间操作返回的是一个新的 Stream,可以继续进行链式调用。以下是一些常见的中间操作:
(1)filter
filter(Predicate<? super T> predicate): 过滤元素。
示例: 过滤出列表中所有偶数。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
@ToString
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
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]
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 19, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 21, "mazi");
List<Demo> userList = Arrays.asList(user,user1,user2,user3);
List<Demo> result = userList.stream()
.filter(n -> n.age % 2 == 0)
.collect(Collectors.toList());
System.out.println(result); //[Demo(name=张三, age=18, pinyin=zhangsan), Demo(name=王二, age=20, pinyin=wanger)]
}
}
(2)map
map(Function<? super T, ? extends R> mapper): 转换每个元素到对应的结果。
示例: 将每个字符串转换为大写。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
@ToString
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("hello", "world");
List<String> upperCaseWords = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(upperCaseWords); // 输出 [HELLO, WORLD]
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 19, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 21, "mazi");
List<Demo> userList = Arrays.asList(user,user1,user2,user3);
List<String> result = userList.stream()
.map(u -> u.pinyin.toUpperCase())
.collect(Collectors.toList());
System.out.println(result); //[ZHANGSAN, LISI, WANGER, MAZI]
}
}
(3)flatMap
flatMap(Function<? super T, ? extends Stream<? extends R>> mapper): 将每个元素转换成另一个 Stream,然后将所有流连接成一个流。
示例:将包含单词列表的列表转换为单词流。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
@ToString
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<List<String>> listOfLists = Arrays.asList(
Arrays.asList("hello", "world"),
Arrays.asList("goodbye", "world")
);
List<String> words = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
System.out.println(words); // 输出 [hello, world, goodbye, world]
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 19, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 21, "mazi");
List<Demo> userList1 = Arrays.asList(user,user1);
List<Demo> userList2 = Arrays.asList(user2,user3);
List<List<Demo>> list = Arrays.asList(userList1,userList2);
List<Demo> result = list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
System.out.println(result);
}
}
(4)sorted
peek(Consumer<? super T> action): 用于调试,允许你无修改地查看流中的元素。
sorted(): 对元素进行自然排序。
示例:对整数列表进行自然排序。
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
@ToString
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9);
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNumbers); // 输出 [1, 1, 3, 4, 5, 9]
List<String> words = Arrays.asList("banana", "apple", "cherry");
List<String> sortedWords = words.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
System.out.println(sortedWords); // 输出 [cherry, banana, apple]
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
List<Demo> userList = Arrays.asList(user,user1,user3,user2);
List<Demo> result = userList.stream()
.sorted(Comparator.comparing(Demo::getAge))
.collect(Collectors.toList());
System.out.println(result);
}
}
(5)peek
peek(Consumer<? super T> action): 用于调试,允许你无修改地查看流中的元素。
示例:打印每个元素,用于调试。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("hello", "world");
List<String> upperCaseWords = words.stream()
.peek(System.out::println) // 打印每个元素
.map(String::toUpperCase)
.collect(Collectors.toList());
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
List<Demo> userList = Arrays.asList(user,user1,user3,user2);
List<Demo> result = userList.stream()
.sorted(Comparator.comparing(Demo::getAge))
.peek(System.out::println) // 打印每个元素
.collect(Collectors.toList());
System.out.println(result);
}
}
( 6) limit
limit(long maxSize): 限制流的大小。
示例:限制流的大小。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
List<Integer> limitedNumbers = numbers.stream()
.limit(3)
.collect(Collectors.toList());
System.out.println(limitedNumbers); // 输出 [1, 2, 3]
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
List<Demo> userList = Arrays.asList(user,user1,user3,user2);
List<Demo> result = userList.stream()
.sorted(Comparator.comparing(Demo::getAge))
.limit(3) // 前三个元素
.collect(Collectors.toList());
System.out.println(result);
}
}
(7) skip
skip(long n): 跳过流中的前 n 个元素。
示例:跳过列表中的前 n 个元素。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
List<Integer> skippedNumbers = numbers.stream()
.skip(3)
.collect(Collectors.toList());
System.out.println(skippedNumbers); // 输出 [4, 5, 6, 7, 8, 9]
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
List<Demo> userList = Arrays.asList(user,user1,user3,user2);
List<Demo> result = userList.stream()
.sorted(Comparator.comparing(Demo::getAge))
.skip(3) // 跳过前三个元素
.collect(Collectors.toList());
System.out.println(result);
}
}
(8)distinct
distinct(): 去除重复元素。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5, 5, 5, 6);
List<Integer> distinctNumbers = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(distinctNumbers); // 输出 [1, 2, 3, 4, 5, 6]
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
List<Demo> distinctByPinyin = userList.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(Demo::getPinyin, Function.identity(), (k1, k2) -> k1),
map -> new ArrayList<>(map.values())
));
distinctByPinyin.forEach(System.out::println);
}
}
终端操作(Terminal operations)
终端操作返回的是一个结果或一个副作用(例如打印结果),之后不能再对 Stream 进行操作。以下是一些常见的终端操作:
(1)forEach
forEach(Consumer<? super T> action): 对每个元素执行一个操作。
示例:对每个元素执行打印操作。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:打印每个元素
words.stream().forEach(System.out::println);
// apple
// banana
// cherry
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
List<Demo> distinctByPinyin = userList.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(Demo::getPinyin, Function.identity(), (p1, p2) -> p1),
map -> new ArrayList<>(map.values())
));
distinctByPinyin.forEach(System.out::println);
}
}
(2) collect
collect(Collector<? super T, A, R> collector): 将流转换为其他形式,如列表、集合或 Map。
示例:将流转换为列表。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:将流转换为列表 [APPLE, BANANA, CHERRY]
List<String> upperCaseWords = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(upperCaseWords);
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
List<Demo> distinctByPinyin = userList.stream()
.peek(u -> u.setPinyin(u.getPinyin().toUpperCase()))
.collect(Collectors.toList());
distinctByPinyin.forEach(System.out::println);
}
}
(3) reduce
reduce(T identity, BinaryOperator accumulator): 通过一个起始值,反复利用 BinaryOperator 来处理和累积元素,返回一个值。
示例:使用 Integer::sum 作为累加器,将流中的整数相加。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 预期结果:计算总和 15
int sum = numbers.stream().reduce(0, Integer::sum);
System.out.println(sum); // 15
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
int totalAge = userList.stream()
.mapToInt(Demo::getAge)
.reduce(0, Integer::sum);
System.out.println( totalAge);
int sumT = userList.stream().mapToInt(Demo::getAge)
.sum();
System.out.println(sumT);
}
}
reduce(BinaryOperator accumulator): 使用一个 BinaryOperator 来累积元素,返回一个 Optional。
示例: 使用 Integer::max 作为累加器,找到流中的最大值。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 预期结果:找到最大值 5
Optional<Integer> max = numbers.stream().reduce(Integer::max);
max.ifPresent(System.out::println); // 5
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
int maxAge = userList.stream()
.mapToInt(Demo::getAge)
.reduce(0, Integer::max);
System.out.println( maxAge);
OptionalInt maxAgeT = userList.stream().mapToInt(Demo::getAge)
.max();
int a=maxAgeT.getAsInt();
System.out.println(a);
}
}
(4)toArray
toArray(): 将流转换为对象数组。
示例:使用 toArray 方法将流转换为对象数组。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:将流转换为对象数组 [apple, banana, cherry]
Object[] wordArray = words.stream().toArray();
System.out.println(Arrays.toString(wordArray));
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
Object[] array = userList.stream().toArray();
System.out.println(array);
}
}
toArray(IntFunction<A[]> generator): 将流转换为特定类型的数组。
示例:使用 toArray 方法将流转换为特定类型的数组。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:将流转换为字符串数组 [apple, banana, cherry]
String[] wordArray = words.stream().toArray(String[]::new);
System.out.println(Arrays.toString(wordArray));
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
Demo[] array = userList.stream().toArray(Demo[]:: new);
Arrays.stream(array).forEach(System.out::println);
}
}
(5)min
min(Comparator<? super T> comparator): 找到最小元素。
示例:使用 min 方法找到流中的最小元素。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:找到最小元素 apple
Optional<String> min = words.stream().min(String::compareTo);
min.ifPresent(System.out::println); // apple
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
OptionalInt maxAgeT = userList.stream().mapToInt(Demo::getAge)
.min().orElse(-1); // 提供一个默认值,以防列表为空
int a=maxAgeT.getAsInt();
System.out.println(a);
}
}
(6)max
max(Comparator<? super T> comparator): 找到最大元素。
示例:使用 max 方法找到流中的最大元素。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:找到最大元素 cherry
Optional<String> max = words.stream().max(String::compareTo);
max.ifPresent(System.out::println); // cherry
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
OptionalInt maxAgeT = userList.stream().mapToInt(Demo::getAge)
.max().orElse(-1); // 提供一个默认值,以防列表为空
int a=maxAgeT.getAsInt();
System.out.println(a);
}
}
(7)count
count(): 返回流中元素的数量。
示例:使用 count 方法返回流中元素的数量。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:流中元素的数量 3
long count = words.stream().count();
System.out.println(count); // 3
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
long count1 = userList.stream().count();
System.out.println(count1);
}
}
(8)anyMatch
anyMatch(Predicate<? super T> predicate): 检查是否至少有一个元素匹配给定的谓词。
示例: 这个方法用于检查流中是否至少有一个元素匹配给定的谓词。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:至少有一个元素以 "a" 开头
boolean anyMatch = words.stream().anyMatch(s -> s.startsWith("a"));
System.out.println(anyMatch); // 输出 true
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
boolean t = userList.stream().anyMatch(s -> s.pinyin.startsWith("zhang"));
System.out.println(t);//true
}
}
(9)allMatch
allMatch(Predicate<? super T> predicate): 检查是否所有元素都匹配给定的谓词。
示例:这个方法用于检查流中是否所有元素都匹配给定的谓词。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:所有元素都以 "c" 开头
boolean allMatch = words.stream().allMatch(s -> s.startsWith("c"));
System.out.println(allMatch); // 输出 false
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
boolean t = userList.stream().allMatch(s -> s.pinyin.startsWith("zhang"));
System.out.println(t); //false
}
}
(10)noneMatch
noneMatch(Predicate<? super T> predicate): 检查是否没有元素匹配给定的谓词。
示例: 这个方法用于检查流中是否没有元素匹配给定的谓词。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:没有元素以 "z" 开头
boolean noneMatch = words.stream().noneMatch(s -> s.startsWith("z"));
System.out.println(noneMatch); // 输出 true
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
boolean t = userList.stream().noneMatch(s -> s.pinyin.startsWith("zhang"));
System.out.println(t);
}
}
(11)findFirst
findFirst(): 返回第一个元素。
示例:这个方法用于返回流中的第一个元素。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:返回第一个元素 "apple"
Optional<String> first = words.stream().findFirst();
first.ifPresent(System.out::println); // apple
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
Optional<Demo> t = userList.stream().findFirst();
t.ifPresent(System.out::println);
}
}
(12)findAny
findAny(): 返回任意一个元素(在并行流中特别有用)。
示例:这个方法用于返回流中的任意一个元素。
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@AllArgsConstructor
@Data
public class Demo {
private String name;
private Integer age;
private String pinyin;
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 预期结果:返回任意一个元素,可能是 "apple", "banana" 或 "cherry"
Optional<String> any = words.stream().findAny();
any.ifPresent(System.out::println); // 输出一个随机的字符串元素
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
Optional<Demo> t = userList.stream().findAny();
t.ifPresent(System.out::println);
}
}
创建 Stream
(1) stream
通过集合的 stream() 方法。
示例:
List<String> list = Arrays.asList("apple", "banana", "cherry");
Stream<String> stream = list.stream();
(2) Arrays.stream
通过数组的 Arrays.stream(Object[]) 方法。
String[] array = {"apple", "banana", "cherry"};
Stream<String> stream = Arrays.stream(array);
(3) Stream.of
使用 Stream.of(T… values) 静态方法。
示例:
Stream<String> stream = Stream.of("apple", "banana", "cherry");
(4) Stream.iterate
使用 Stream.iterate(T seed, UnaryOperator f)或 Stream.generate(Supplier s) 创建无限流。
// 使用 Stream.iterate 创建无限流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1);
infiniteStream.forEach(System.out::println);
// 使用 Stream.generate 创建无限流
Stream<String> generateStream = Stream.generate(() -> "hello");
generateStream.forEach(System.out::println);
并行 Streams
Stream 接口还有一个子接口 BaseStream 和一个并行流接口 ParallelStream,用于并行处理数据。
并行流可以提高处理大量数据时的性能,因为它可以利用多核处理器的能力来并行地执行操作。但是,并不是所有的流操作都适合并行处理,你需要根据具体的情况来决定是否使用并行流
(1)parallelStream
parallelStream() 方法,该方法是 Stream 接口的一个扩展方法。
示例:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
// 创建并行流
List<Integer> evenNumbers = numbers.parallelStream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(evenNumbers); // 输出 [2, 4, 6, 8]
(2)parallel
parallel() 方法,该方法是 BaseStream 接口的一个扩展方法。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
// 使用 parallel() 方法创建并行流
List<Integer> evenNumbers = numbers.stream()
.parallel() // 创建并行流
.filter(n -> n % 2 == 0) // 过滤偶数
.collect(Collectors.toList()); // 收集结果
System.out.println(evenNumbers); // 输出 [2, 4, 6, 8]
Collectors
Collectors 类提供了很多静态方法,用于实现常见的归约操作,如将元素累积到集合、字符串、Map 等。
(1)toList
toList(): 将流中的元素收集到列表中。
List<String> words = Arrays.asList("apple", "banana", "cherry");
List<String> collectedWords = words.stream().collect(Collectors.toList());
System.out.println(collectedWords); // 输出 [apple, banana, cherry]
(2)toSet
toSet(): 将流中的元素收集到集合中,自动去除重复项。
示例:
List<String> words = Arrays.asList("apple", "banana", "cherry", "apple", "banana");
Set<String> collectedWords = words.stream().collect(Collectors.toSet());
System.out.println(collectedWords); // 输出 [apple, banana, cherry]
(3)toMap
toMap(): 将流中的元素收集到 Map 中,其中流中的元素作为键或值。
示例:
List<String> words = Arrays.asList("apple", "banana", "cherry");
Map<String, Integer> wordCount = words.stream().collect(Collectors.toMap(
word -> word,
word -> word.length()
));
System.out.println(wordCount); // 输出 {apple=5, banana=6, cherry=6}
Demo user = new Demo("张三", 18, "zhangsan");
Demo user1 = new Demo("李四", 39, "lisi");
Demo user2 = new Demo("王二", 20, "wanger");
Demo user3 = new Demo("麻子", 11, "mazi");
Demo user4 = new Demo("张三", 19, "zhangsan");
List<Demo> userList = Arrays.asList(user,user1,user3,user2,user4);
Map<String, Demo> collect = userList.stream().collect(Collectors.toMap(Demo::getPinyin, Demo -> Demo, (k1, k2) -> k1));
System.out.println(collect );
(4)joining
joining(): 将流中的元素连接成一个字符串。
示例:
List<String> words = Arrays.asList("apple", "banana", "cherry");
String joinedString = words.stream().collect(Collectors.joining("-"));
System.out.println(joinedString); // 输出 apple-banana-cherry
(5)counting
counting(): 计算流中元素的数量。
示例:
List<String> words = Arrays.asList("apple", "banana", "cherry");
long wordCount = words.stream().collect(Collectors.counting());
System.out.println(wordCount); // 输出 3
使用 Stream 的注意事项
1、流一旦执行终端操作,就会被消耗掉,不可以再使用该流执行其他操作。
2、流操作不会改变原始数据源,所有的操作都会返回一个新的 Stream 对象。
3、流操作可以并行化,但需要注意线程安全和数据竞争问题。