Lambda表达式
Lambda表达式是Java 8引入的重要特性,它是一种匿名函数,可以让你更简洁地编写代码。
基本语法
(parameters) -> expression
(parameters) -> { statements; }
示例
// 无参数,单条语句
() -> System.out.println("Hello World")
// 单参数,单条语句
x -> x * x
// 多参数,多条语句
(x, y) -> {
int sum = x + y;
return sum;
}
Stream API
Stream API是Java 8中处理集合数据的重要工具,它提供了一种声明式的方式来处理数据集合。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
主要特点
- 函数式编程:支持链式调用和函数式操作
- 惰性求值:中间操作不会立即执行
- 并行处理:支持并行流处理大数据集
Stream 流程
Stream API 的操作流程通常遵循以下模式:
- 创建流 - 从数据源创建
Stream - 中间操作 - 对流进行一系列转换操作(可链式调用)
- 终端操作 - 产生最终结果(只能有一个终端操作)
List<String> result = list.stream() // 创建流
.filter(s -> !s.isEmpty()) // 中间操作
.map(String::toUpperCase) // 中间操作
.sorted() // 中间操作
.collect(Collectors.toList()); // 终端操作
Stream API速查
1. 中间操作(Intermediate Operations)
基础过滤和转换
filter(Predicate<T> predicate)
List<String> list = Arrays.asList("apple", "", "banana", "");
List<String> nonEmpty = list.stream()
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
// 结果: ["apple", "banana"]
map(Function<T,R> mapper)
List<String> words = Arrays.asList("hello", "world");
List<Integer> lengths = words.stream()
.map(String::length)
.collect(Collectors.toList());
// 结果: [5, 5]
flatMap(Function<T,Stream<R>> mapper)
List<List<String>> listOfLists = Arrays.asList(
Arrays.asList("a", "b"),
Arrays.asList("c", "d")
);
List<String> flattened = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// 结果: ["a", "b", "c", "d"]
去重和排序
distinct()
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4);
List<Integer> unique = numbers.stream()
.distinct()
.collect(Collectors.toList());
// 结果: [1, 2, 3, 4]
sorted()
List<Integer> numbers = Arrays.asList(3, 1, 4, 2);
List<Integer> sorted = numbers.stream()
.sorted()
.collect(Collectors.toList());
// 结果: [1, 2, 3, 4]
sorted(Comparator<T> comparator)
List<String> words = Arrays.asList("apple", "pie", "cherry");
List<String> sortedByLength = words.stream()
.sorted(Comparator.comparing(String::length))
.collect(Collectors.toList());
// 结果: ["pie", "apple", "cherry"]
限制和跳过
limit(long maxSize)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> firstThree = numbers.stream()
.limit(3)
.collect(Collectors.toList());
// 结果: [1, 2, 3]
skip(long n)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> afterSecond = numbers.stream()
.skip(2)
.collect(Collectors.toList());
// 结果: [3, 4, 5]
调试和窥视
peek(Consumer<T> action)
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<Integer> result = numbers.stream()
.peek(System.out::println)
.map(n -> n * 2)
.collect(Collectors.toList());
// 输出: 1, 2, 3
// 结果: [2, 4, 6]
2. 终端操作(Terminal Operations)
收集和转换
collect(Collector<T,A,R> collector)
List<String> words = Arrays.asList("hello", "world");
List<String> collected = words.stream()
.collect(Collectors.toList());
toArray()
List<String> words = Arrays.asList("hello", "world");
Object[] array = words.stream().toArray();
// 结果: ["hello", "world"]
toArray(IntFunction<T[]> generator)
List<String> words = Arrays.asList("hello", "world");
String[] array = words.stream().toArray(String[]::new);
// 结果: ["hello", "world"]
遍历操作
forEach(Consumer<T> action)
List<String> words = Arrays.asList("hello", "world");
words.stream().forEach(System.out::println);
// 输出: hello, world
forEachOrdered(Consumer<T> action)
List<String> words = Arrays.asList("hello", "world");
words.parallelStream().forEachOrdered(System.out::println);
// 保证输出顺序: hello, world
归约操作
reduce(BinaryOperator<T> accumulator)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
Optional<Integer> sum = numbers.stream()
.reduce(Integer::sum);
// 结果: Optional[10]
reduce(T identity, BinaryOperator<T> accumulator)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
Integer sum = numbers.stream()
.reduce(0, Integer::sum);
// 结果: 10
reduce(U identity, BiFunction<U,T,U> accumulator, BinaryOperator<U> combiner)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
Integer sum = numbers.parallelStream()
.reduce(0, Integer::sum, Integer::sum);
// 结果: 10
查找和匹配
findFirst()
List<String> words = Arrays.asList("apple", "banana", "cherry");
Optional<String> first = words.stream()
.filter(s -> s.startsWith("b"))
.findFirst();
// 结果: Optional["banana"]
findAny()
List<String> words = Arrays.asList("apple", "banana", "cherry");
Optional<String> any = words.parallelStream()
.filter(s -> s.startsWith("b"))
.findAny();
// 结果: Optional["banana"] (任意一个)
anyMatch(Predicate<T> predicate)
List<String> words = Arrays.asList("apple", "banana", "cherry");
boolean hasLongWord = words.stream()
.anyMatch(s -> s.length() > 5);
// 结果: true
allMatch(Predicate<T> predicate)
List<String> words = Arrays.asList("apple", "banana", "cherry");
boolean allLong = words.stream()
.allMatch(s -> s.length() > 3);
// 结果: true
noneMatch(Predicate<T> predicate)
List<String> words = Arrays.asList("apple", "banana", "cherry");
boolean noEmpty = words.stream()
.noneMatch(String::isEmpty);
// 结果: true
统计操作
count()
List<String> words = Arrays.asList("apple", "banana", "cherry");
long count = words.stream().count();
// 结果: 3
min(Comparator<T> comparator)
List<String> words = Arrays.asList("apple", "banana", "cherry");
Optional<String> shortest = words.stream()
.min(Comparator.comparing(String::length));
// 结果: Optional["apple"]
max(Comparator<T> comparator)
List<String> words = Arrays.asList("apple", "banana", "cherry");
Optional<String> longest = words.stream()
.max(Comparator.comparing(String::length));
// 结果: Optional["banana"] 或 Optional["cherry"]
3. Collectors 收集器
基础收集
toList()
List<String> words = Arrays.asList("hello", "world");
List<String> list = words.stream()
.collect(Collectors.toList());
toSet()
List<String> words = Arrays.asList("hello", "world", "hello");
Set<String> set = words.stream()
.collect(Collectors.toSet());
// 结果: {"hello", "world"}
toCollection(Supplier<Collection<T>> collectionFactory)
List<String> words = Arrays.asList("hello", "world");
LinkedList<String> linkedList = words.stream()
.collect(Collectors.toCollection(LinkedList::new));
字符串连接
joining()
List<String> words = Arrays.asList("hello", "world");
String joined = words.stream()
.collect(Collectors.joining());
// 结果: "helloworld"
joining(CharSequence delimiter)
List<String> words = Arrays.asList("hello", "world");
String joined = words.stream()
.collect(Collectors.joining(", "));
// 结果: "hello, world"
joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
List<String> words = Arrays.asList("hello", "world");
String joined = words.stream()
.collect(Collectors.joining(", ", "[", "]"));
// 结果: "[hello, world]"
分组和分区
groupingBy(Function<T,K> classifier)
List<String> words = Arrays.asList("apple", "ant", "banana", "cat");
Map<Character, List<String>> grouped = words.stream()
.collect(Collectors.groupingBy(s -> s.charAt(0)));
// 结果: {'a': ["apple", "ant"], 'b': ["banana"], 'c': ["cat"]}
groupingBy(Function<T,K> classifier, Collector<T,A,D> downstream)
List<String> words = Arrays.asList("apple", "ant", "banana", "cat");
Map<Character, Long> countByFirstChar = words.stream()
.collect(Collectors.groupingBy(
s -> s.charAt(0),
Collectors.counting()
));
// 结果: {'a': 2, 'b': 1, 'c': 1}
partitioningBy(Predicate<T> predicate)
List<String> words = Arrays.asList("apple", "ant", "banana", "cat");
Map<Boolean, List<String>> partitioned = words.stream()
.collect(Collectors.partitioningBy(s -> s.length() > 3));
// 结果: {true: ["apple", "banana"], false: ["ant", "cat"]}
统计收集
summingInt(ToIntFunction<T> mapper)
List<String> words = Arrays.asList("apple", "ant", "banana");
int totalLength = words.stream()
.collect(Collectors.summingInt(String::length));
// 结果: 13
averagingInt(ToIntFunction<T> mapper)
List<String> words = Arrays.asList("apple", "ant", "banana");
double avgLength = words.stream()
.collect(Collectors.averagingInt(String::length));
// 结果: 4.333...
综合统计
summarizingInt(ToIntFunction<T> mapper)
List<String> words = Arrays.asList("apple", "ant", "banana");
IntSummaryStatistics stats = words.stream()
.collect(Collectors.summarizingInt(String::length));
// 包含: count, sum, min, average, max
映射和转换
mapping(Function<T,U> mapper, Collector<U,A,R> downstream)
List<String> words = Arrays.asList("apple", "ant", "banana");
Map<Character, Set<Integer>> result = words.stream()
.collect(Collectors.groupingBy(
s -> s.charAt(0),
Collectors.mapping(
String::length,
Collectors.toSet()
)
));
// 结果: {'a': {5, 3}, 'b': {6}}
最值收集
maxBy(Comparator<T> comparator)
List<String> words = Arrays.asList("apple", "ant", "banana");
Optional<String> longest = words.stream()
.collect(Collectors.maxBy(Comparator.comparing(String::length)));
// 结果: Optional["banana"]
4. 并行流操作
parallel()
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> doubled = numbers.parallelStream()
.map(n -> n * 2)
.collect(Collectors.toList());
sequential()
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = numbers.parallelStream()
.sequential()
.map(n -> n * 2)
.collect(Collectors.toList());
unordered()
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = numbers.parallelStream()
.unordered()
.distinct()
.collect(Collectors.toList());
:: 是 Java 8 引入的方法引用操作符(Method Reference Operator)。
主要用途
- 简化 Lambda 表达式 - 当 Lambda 表达式只是调用一个现有方法时,可以用方法引用来替代
四种方法引用形式
- 静态方法引用 -
ClassName::staticMethod
List<String> list = Arrays.asList("1", "2", "3");
List<Integer> numbers = list.stream()
.map(Integer::parseInt) // 等价于 s -> Integer.parseInt(s)
.collect(Collectors.toList());
- 实例方法引用 -
instance::method
List<String> list = Arrays.asList("hello", "world");
list.forEach(System.out::println); // 等价于 s -> System.out.println(s)
- 对象方法引用 -
ClassName::method
List<String> list = Arrays.asList("hello", "world");
List<String> upper = list.stream()
.map(String::toUpperCase) // 等价于 s -> s.toUpperCase()
.collect(Collectors.toList());
- 构造方法引用 -
ClassName::new
List<String> list = Arrays.asList("hello", "world");
Stream<StringBuilder> builders = list.stream()
.map(StringBuilder::new); // 等价于 s -> new StringBuilder(s)
方法引用使代码更加简洁易读,是 Stream API 中常用的语法糖。