Java lambda表达式

lambda表达式是Java 8 中的一个很重要的新特性,它容许将行为传到函数中。在Java 8 之前,如果我们想要把行为传到函数中,仅有的选择就是匿名内部类。但Java 8 发布以后,lambda表达式将大量替代匿名内部类的使用,简化代码,突出匿名内部类中最重要的逻辑代码。下面以Runable接口说明这一点:

Runnable runnable = new Runnable() {
      @Override
      public void run() {
        System.out.println(Thread.currentThread().getName());
      }
    };

使用lambda表达式简化:

Runnable runnable1 = () -> System.out.println(Thread.currentThread().getName());

一、lambda表达式简介

lambda表达式是一个匿名函数,一种没有声明的方法,没有修饰符,返回值声明和名称。Java中的lambda表达式通常使用语法是(parameters) -> (expression)(parameters) ->{ statements; },例如:

// 接收两个int型参数,返回它们的值
(int a, int b) -> {  return a + b; }
// 无参数
() -> System.out.println("Hello World");
// 接收一个String型字符串,打印字符串
(String s) -> { System.out.println(s); }
// 无参数 返回 42
() -> 42
// 无参数,返回3.1415
() -> { return 3.1415 };

lambda表达式的结构说明:

  • Lambda 表达式可以具有零个,一个或多个参数;
  • 可以显式声明参数的类型,也可以由编译器自动从上下文推断参数的类型。例如 (int a) 与刚才相同 (a);
  • 参数用小括号括起来,用逗号分隔。例如 (a, b) 或 (int a, int b) 或 (String a, int b, float c);
  • 空括号用于表示一组空的参数。例如 () -> 42;
  • 当有且仅有一个参数时,如果不显式指明类型,则不必使用小括号。例如 a -> return a*a;
  • Lambda 表达式的正文可以包含零条,一条或多条语句;
  • 如果 Lambda 表达式的正文只有一条语句,则大括号可不用写,且表达式的返回值类型要与匿名函数的返回类型相同;
  • 如果 Lambda 表达式的正文有一条以上的语句必须包含在大括号(代码块)中,且表达式的返回值类型要与匿名函数的返回类型相同。

二、lambda表达式示例

1. 使用Java 8 lambda表达式进行事件处理

java 8 之前:

JButton show =  new JButton("Show");
    show.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        System.out.println("Hello world");
      }
    });

java 8 :

show.addActionListener((e) -> {
    System.out.println("Hello world");
});
2. 使用Java 8 lambda表达式进行列表迭代

java 8 之前:

List<String> items = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String item : items) {
  System.out.println(item);
}

java 8 :

items.forEach(item -> System.out.println(item));

java 8 之前:

Map<String,String> map = new HashMap <>();
map.put("1","a");
map.put("2","b");
map.put("3","c");
for(String key : map.keySet()){
  System.out.println(map.get(key));
}

java 8 :

map.forEach((k,v)->System.out.println(map.get(k)));
3. 使用lambda表达式和函数式接口Predicate进行逻辑操作

Java 8 添加了一个 java.util.function 的包。它包含了很多类,用来支持Java的函数式编程。其中一个便是Predicate,使用 java.util.function.Predicate 函数式接口以及lambda表达式,可以向API方法添加逻辑,用更少的代码支持更多的动态行为。

public static void main(String[] arg){
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

    System.out.print("输出所有数字:");
    evaluate(list, (n) -> true);

    System.out.print("不输出:");
    evaluate(list, (n) -> false);

    System.out.print("输出偶数:");
    evaluate(list, (n) -> n % 2 == 0);

    System.out.print("输出奇数:");
    evaluate(list, (n) -> n % 2 == 1);

    System.out.print("输出大于 5 的数字:");
    evaluate(list, (n) -> n > 5);
  }
  public static void evaluate(List<Integer> list, Predicate<Integer> predicate) {
//    for (Integer n : list) {
//      if (predicate.test(n)) {
//        System.out.print(n + " ");
//      }
//    }
    list.stream().filter(name -> predicate.test(name)).forEach(name -> System.out.println(name+" "));
  }
4. 多个Predicate合并使用

java.util.function.Predicate允许将两个或更多的 Predicate 合成一个。它提供类似于逻辑操作符AND和OR的方法,名字叫做and()、or()和xor(),用于将传入 filter() 方法的条件合并起来。例如,要得到所有以J开始,长度为四个字母的语言,可以定义两个独立的 Predicate 示例分别表示每一个条件,然后用 Predicate.and() 方法将它们合并起来,如下所示:

List<String> list = Arrays.asList("Java", "C", "C++", "Ruby", "C#", "Go");

Predicate<String> startsWithJ = (n) -> n.startsWith("J");
Predicate<String> fourLetterLong = (n) -> n.length() == 4;
list.stream()
        .filter(startsWithJ.and(fourLetterLong))
        .forEach((n) -> System.out.print("nName, which starts with 'J' and four letter long is : " + n));
5. Java 8中使用lambda表达式的Map和Reduce

java.util.stream.Stream接口 和 Lambda 表达式一样,都是 Java 8 新引入的。所有 Stream 的操作必须以 Lambda 表达式为参数。Stream 接口中带有大量有用的方法,比如 map() 的作用就是将 input Stream 的每个元素映射成output Stream 的另外一个元素。

下面的例子,我们将 Lambda 表达式 x -> x*x 传递给map()方法,将其应用于流的所有元素。之后,我们使用forEach打印列表的所有元素:
java 8 之前:

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
for(Integer n : list) {
    int x = n * n;
    System.out.println(x);
}

java 8 :

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
list.stream().map((x) -> x*x).forEach(System.out::println);

下面的示例中,我们给定一个列表,然后求列表中每个元素的平方和。这个例子中,我们使用了 reduce() 方法,这个方法的主要作用是把 Stream 元素组合起来:
java 8 之前:

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
int sum = 0;
for(Integer n : list) {
    int x = n * n;
    sum = sum + x;
}
System.out.println(sum);

java 8 :

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
int sum = list.stream().map(x -> x*x).reduce((x,y) -> x + y).get();
System.out.println(sum);
6. 通过过滤创建一个String列表

过滤是Java开发者在大规模集合上的一个常用操作,而现在使用lambda表达式和流API过滤大规模数据集合是惊人的简单。流提供了一个 filter() 方法,接受一个 Predicate 对象,即可以传入一个lambda表达式作为过滤逻辑。下面的例子是用lambda表达式过滤Java集合,将帮助理解。

List<String> strList = Arrays.asList("Java", "C", "C++", "Ruby", "C#", "Go");
// 创建一个字符串列表,每个字符串长度大于2
List<String> filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);
7. 去重操作

本例展示了如何利用流的 distinct() 方法来对集合进行去重:

List<Integer> numbers = Arrays.asList(9, 10, 3, 4, 7, 3, 4);
List<Integer> distinct = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
System.out.printf("Original List : %s,  Square Without duplicates : %s %n", numbers, distinct);
8. 计算集合元素的最大值、最小值、总和以及平均值

IntStream、LongStream 和 DoubleStream 等流的类中,有个非常有用的方法叫做 summaryStatistics()。可以返回 IntSummaryStatistics、LongSummaryStatistics 或者 DoubleSummaryStatistic s,描述流中元素的各种摘要数据。在本例中,我们用这个方法来计算列表的最大值和最小值。它也有 getSum() 和 getAverage() 方法来获得列表的所有元素的总和及平均值。

//获取数字的个数、最小值、最大值、总和以及平均值
List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Highest prime number in List : " + stats.getMax());
System.out.println("Lowest prime number in List : " + stats.getMin());
System.out.println("Sum of all prime numbers : " + stats.getSum());
System.out.println("Average of all prime numbers : " + stats.getAverage());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值