全面解读 Java Lambda 表达式:从基础语法到实战应用

Lambda表达式

1.Predicate

java.util.function.Predicate 是 Java 8 引入的一个函数式接口,代表一个接受单一输入参数并返回布尔值(truefalse)的函数。它常用于流(Streams)操作中,比如过滤(filter)或其他条件判断。

示例 1:基本用法

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        // 创建一个Predicate,判断一个数字是否大于10
        Predicate<Integer> isGreaterThan10 = num -> num > 10;

        // 测试Predicate
        System.out.println(isGreaterThan10.test(15));  // 输出: true
        System.out.println(isGreaterThan10.test(5));   // 输出: false
    }
}

示例 2:结合 and, or, negate 方法

Predicate 接口提供了一些默认方法,允许组合多个 Predicate 对象:

  • and:将两个 Predicate 组合为一个,只有当两个条件都为 true 时,返回 true
  • or:将两个 Predicate 组合为一个,任何一个条件为 true 时,返回 true
  • negate:将一个 Predicate 取反,即当原条件为 true 时,返回 false,反之亦然。
import java.util.function.Predicate;

public class PredicateCombinationExample {
    public static void main(String[] args) {
        Predicate<Integer> isGreaterThan10 = num -> num > 10;
        Predicate<Integer> isLessThan20 = num -> num < 20;

        // 使用and组合Predicate,判断一个数字是否大于10且小于20
        Predicate<Integer> isBetween10And20 = isGreaterThan10.and(isLessThan20);

        System.out.println(isBetween10And20.test(15));  // 输出: true
        System.out.println(isBetween10And20.test(5));   // 输出: false

        // 使用or组合Predicate,判断一个数字是否小于10或大于20
        Predicate<Integer> isLessThan10OrGreaterThan20 = isGreaterThan10.negate().or(isLessThan20.negate());

        System.out.println(isLessThan10OrGreaterThan20.test(5));   // 输出: true
        System.out.println(isLessThan10OrGreaterThan20.test(25));  // 输出: true
        System.out.println(isLessThan10OrGreaterThan20.test(15));  // 输出: false
    }
}

示例 3:在流中使用 Predicate

Predicate 经常与 Java 流(Streams)一起使用,尤其是在 filter 操作中,可以过滤符合条件的元素。

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateStreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(5, 10, 15, 20, 25, 30);

        // 创建Predicate,判断数字是否为偶数
        Predicate<Integer> isEven = num -> num % 2 == 0;

        // 使用filter和Predicate来过滤偶数
        List<Integer> evenNumbers = numbers.stream()
                                           .filter(isEven)
                                           .collect(Collectors.toList());

        System.out.println(evenNumbers);  // 输出: [10, 20, 30]
    }
}

示例 4:使用 Predicate 作为方法参数

你还可以将 Predicate 作为方法的参数来动态传递过滤条件。

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateAsParameterExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Eva");

        // 过滤名字长度大于3的名字
        List<String> filteredNames = filterNames(names, name -> name.length() > 3);

        System.out.println(filteredNames);  // 输出: [Alice, Charlie, David]
    }

    // 使用Predicate作为参数
    public static List<String> filterNames(List<String> names, Predicate<String> predicate) {
        return names.stream()
                    .filter(predicate)
                    .collect(Collectors.toList());
    }
}

在这个例子中,filterNames 方法接受一个 List<String> 和一个 Predicate<String> 作为参数,从而让你可以在不同的情况下传入不同的过滤条件。

2.常用的Stream()方法:

Stream 中,常用的方法可以分为两大类:

  1. 中间操作(返回一个新的 Stream,是惰性求值的)
  2. 终止操作(触发流的实际计算,产生一个结果,通常是单一的值或收集后的容器)

下面是常用的 Stream 方法的详细介绍。

1. 中间操作(Intermediate Operations)

中间操作会返回一个新的 Stream,并且是惰性求值的,意味着只有在最终操作被执行时,流才会开始处理。

filter(Predicate<? super T> predicate)

filter() 用于通过提供的 Predicate 筛选出符合条件的元素。

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]
map(Function<? super T, ? extends R> mapper)

map() 用于将流中的每个元素应用一个函数,映射成新的元素。

List<String> words = Arrays.asList("apple", "banana", "cherry");
List<Integer> wordLengths = words.stream()
                                 .map(String::length)  // 获取字符串的长度
                                 .collect(Collectors.toList());
System.out.println(wordLengths);  // 输出: [5, 6, 6]
flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

flatMap() 将每个元素映射成一个新的流,然后将这些流"扁平化"成一个单一的流。

List<List<Integer>> listOfLists = Arrays.asList(
        Arrays.asList(1, 2, 3),
        Arrays.asList(4, 5),
        Arrays.asList(6, 7)
);

List<Integer> flatList = listOfLists.stream()
                                   .flatMap(List::stream)  // 扁平化操作
                                   .collect(Collectors.toList());
System.out.println(flatList);  // 输出: [1, 2, 3, 4, 5, 6, 7]
distinct()

distinct() 去除流中的重复元素,返回一个去重后的流。

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> distinctNumbers = numbers.stream()
                                       .distinct()  // 去重
                                       .collect(Collectors.toList());
System.out.println(distinctNumbers);  // 输出: [1, 2, 3, 4, 5]
sorted()

sorted() 用于对流中的元素进行排序,返回一个排序后的流。默认是升序排序。

List<Integer> numbers = Arrays.asList(5, 3, 8, 1, 4);
List<Integer> sortedNumbers = numbers.stream()
                                     .sorted()  // 升序排序
                                     .collect(Collectors.toList());
System.out.println(sortedNumbers);  // 输出: [1, 3, 4, 5, 8]

你也可以传入自定义的 Comparator 来进行降序排序:

List<Integer> sortedNumbersDesc = numbers.stream()
                                          .sorted((a, b) -> b - a)  // 降序排序
                                          .collect(Collectors.toList());
System.out.println(sortedNumbersDesc);  // 输出: [8, 5, 4, 3, 1]
limit(long maxSize)

limit() 用于返回流中的前 n 个元素,常用于截取流的前几个元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> limitedNumbers = numbers.stream()
                                      .limit(3)  // 获取前 3 个元素
                                      .collect(Collectors.toList());
System.out.println(limitedNumbers);  // 输出: [1, 2, 3]
skip(long n)

skip() 用于跳过流中的前 n 个元素,返回剩余的流。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> skippedNumbers = numbers.stream()
                                      .skip(3)  // 跳过前 3 个元素
                                      .collect(Collectors.toList());
System.out.println(skippedNumbers);  // 输出: [4, 5, 6]

2. 终止操作(Terminal Operations)

终止操作会触发流的计算,通常会产生一个结果,或者将结果收集到一个容器中。终止操作执行时,流会开始处理数据。

forEach(Consumer<? super T> action)

forEach() 用于遍历流中的每个元素,常用于消费流中的数据或执行副作用操作。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEach(name -> System.out.println(name));  // 遍历输出每个名字
collect(Collector<? super T, A, R> collector)

collect() 是一个非常常用的终止操作,用于将流中的元素收集到一个容器中。常见的收集器包括 toList()toSet()joining() 等。

List<String> words = Arrays.asList("apple", "banana", "cherry");
List<String> result = words.stream()
                           .filter(word -> word.length() > 5)
                           .collect(Collectors.toList());  // 收集到 List 中
System.out.println(result);  // 输出: [banana, cherry]
reduce(T identity, BinaryOperator<T> accumulator)

reduce() 用于将流中的元素进行归约操作,通常用于求和、求积等操作。它将流中的元素通过二元操作符累计为一个单一的结果。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
                 .reduce(0, (a, b) -> a + b);  // 求和
System.out.println(sum);  // 输出: 15
anyMatch(Predicate<? super T> predicate)

anyMatch() 用于检查流中的元素是否有任何一个满足给定的条件。只要有一个元素满足条件,返回 true,否则返回 false

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEven = numbers.stream()
                         .anyMatch(n -> n % 2 == 0);  // 判断是否存在偶数
System.out.println(hasEven);  // 输出: true
allMatch(Predicate<? super T> predicate)

allMatch() 用于检查流中的所有元素是否都满足给定的条件。如果所有元素都满足条件,返回 true,否则返回 false

List<Integer> numbers = Arrays.asList(2, 4, 6, 8);
boolean allEven = numbers.stream()
                         .allMatch(n -> n % 2 == 0);  // 判断是否所有元素都是偶数
System.out.println(allEven);  // 输出: true
noneMatch(Predicate<? super T> predicate)

noneMatch() 用于检查流中的元素是否都不满足给定的条件。如果没有任何元素满足条件,返回 true,否则返回 false

List<Integer> numbers = Arrays.asList(1, 3, 5, 7);
boolean noEven = numbers.stream()
                        .noneMatch(n -> n % 2 == 0);  // 判断是否没有偶数
System.out.println(noEven);  // 输出: true
max(Comparator<? super T> comparator)min(Comparator<? super T> comparator)

max()min() 分别返回流中的最大值和最小值。它们接受一个 Comparator 来进行排序。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> max = numbers.stream()
                               .max(Integer::compareTo);  // 查找最大值
System.out.println(max.get());  // 输出: 5

Optional<Integer> min = numbers.stream()
                               .min(Integer::compareTo);  // 查找最小值
System.out.println(min.get());  // 输出: 1
count()

count() 用于统计流中元素的数量。

List<String> words = Arrays.asList("apple", "banana", "cherry");
long count = words.stream()
                  .filter(word -> word.length() > 5)
                  .count();  // 统计长度大于 5 的元素个数
System.out.println(count);  // 输出: 2

findFirst()
返回第一个元素的 Optional

Optional<Integer> first = Stream.of(1, 2, 3).findFirst();

findAny()
返回任意一个元素的 Optional(常用于并行流)。

Optional<Integer> any = Stream.of(1, 2, 3).findAny();

3.创建流的常用方法

Stream.of(T… values)
Stream<String> stream = Stream.of("A", "B", "C");
Arrays.stream(T[] array)
Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 3});
Collection.stream()
List<String> list = Arrays.asList("A", "B", "C");
Stream<String> stream = list.stream();
Stream.generate(Supplier s)
Stream<Double> randoms = Stream.generate(Math::random).limit(5);

Stream.iterate(T seed, UnaryOperator f)

产生一个无线流

Stream<Integer> infinite = Stream.iterate(1, n -> n + 1).limit(5);
infinite.forEach(System.out::println); // 输出:1, 2, 3, 4, 5

4.java Stream API中实现 求和分组排序去重 等常见操作的

1. 求和

通过 reducecollect 方法实现。

int sum = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
System.out.println(sum); // 输出:10

使用 mapToIntsum

int sum = Stream.of(1, 2, 3, 4).mapToInt(Integer::intValue).sum();
System.out.println(sum); // 输出:10

对对象中的某个字段求和:

class Item {
    int price;
    Item(int price) { this.price = price; }
}
List<Item> items = Arrays.asList(new Item(10), new Item(20), new Item(30));
int total = items.stream().mapToInt(item -> item.price).sum();
System.out.println(total); // 输出:60
2. 分组

通过 Collectors.groupingBy 方法实现。

按字段分组:

class Person {
    String name;
    int age;
    Person(String name, int age) { this.name = name; this.age = age; }
}
List<Person> people = Arrays.asList(
    new Person("Alice", 30), new Person("Bob", 20), new Person("Charlie", 30)
);
Map<Integer, List<Person>> groupedByAge = people.stream()
    .collect(Collectors.groupingBy(person -> person.age));
System.out.println(groupedByAge);
// 输出:{20=[Bob], 30=[Alice, Charlie]}

分组后统计数量:

Map<Integer, Long> ageCounts = people.stream()
    .collect(Collectors.groupingBy(person -> person.age, Collectors.counting()));
System.out.println(ageCounts);
// 输出:{20=1, 30=2}

分组后求和:

Map<Integer, Integer> ageSum = people.stream()
    .collect(Collectors.groupingBy(
        person -> person.age,
        Collectors.summingInt(person -> person.age)
    ));
System.out.println(ageSum);
// 输出:{20=20, 30=60}
3. 排序

通过 sorted 方法实现。

自然排序(默认排序):

Stream.of(3, 1, 4, 1, 5, 9).sorted().forEach(System.out::println);
// 输出:1, 1, 3, 4, 5, 9

自定义排序:

List<String> names = Arrays.asList("Bob", "Alice", "Charlie");
names.stream()
    .sorted((a, b) -> b.compareTo(a)) // 按逆序排序
    .forEach(System.out::println);
// 输出:Charlie, Bob, Alice

按对象字段排序:

List<Person> people = Arrays.asList(
    new Person("Alice", 30), new Person("Bob", 20), new Person("Charlie", 25)
);
people.stream()
    .sorted(Comparator.comparingInt(person -> person.age)) // 按年龄升序
    .forEach(person -> System.out.println(person.name));
// 输出:Bob, Charlie, Alice
4. 去重

通过 distinct 方法实现。

去除基本类型重复元素:

Stream.of(1, 2, 2, 3, 4, 4).distinct().forEach(System.out::println);
// 输出:1, 2, 3, 4

对对象去重(需要重写 equalshashCode 方法):

class Person {
    String name;
    int age;
    Person(String name, int age) { this.name = name; this.age = age; }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;
        Person person = (Person) o;
        return age == person.age && name.equals(person.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
List<Person> people = Arrays.asList(
    new Person("Alice", 30), new Person("Alice", 30), new Person("Bob", 20)
);
people.stream().distinct().forEach(person -> System.out.println(person.name));
// 输出:Alice, Bob
5. 统计

通过 Collectors 提供的各种统计方法实现

统计数量:

long count = Stream.of(1, 2, 3, 4).count();
System.out.println(count); // 输出:4

求最大值和最小值:

Optional<Integer> max = Stream.of(1, 2, 3, 4).max(Integer::compare);
Optional<Integer> min = Stream.of(1, 2, 3, 4).min(Integer::compare);
System.out.println(max.get()); // 输出:4
System.out.println(min.get()); // 输出:1

求平均值:

Double average = Stream.of(1, 2, 3, 4)
    .collect(Collectors.averagingInt(Integer::intValue));
System.out.println(average); // 输出:2.5

综合统计信息(最大值、最小值、平均值等):

IntSummaryStatistics stats = Stream.of(1, 2, 3, 4)
    .collect(Collectors.summarizingInt(Integer::intValue));
System.out.println(stats.getSum());       // 输出:10
System.out.println(stats.getAverage());  // 输出:2.5
System.out.println(stats.getMax());      // 输出:4
System.out.println(stats.getMin());      // 输出:1
6.合并字符串

通过 Collectors.joining 方法实现。

String result = Stream.of("A", "B", "C").collect(Collectors.joining());
System.out.println(result); // 输出:ABC

带分隔符的拼接:

String result = Stream.of("A", "B", "C").collect(Collectors.joining(", "));
System.out.println(result); // 输出:A, B, C

带前缀和后缀的拼接:

String result = Stream.of("A", "B", "C").collect(Collectors.joining(", ", "[", "]"));
System.out.println(result); // 输出:[A, B, C]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值