Java Lambda 函数式编程 示例详解



一.Lambda表达式


1. Java为何需要Lambda

  • 1996年1月,Java 1.0发布了,此后计算机编程领域发生了翻天覆地的变化。商业发展需要更复杂的应用,大多数程序都跑在更强大的装备多核CPU的机器上。带有高效运行期编译器的Java虚拟机(JVM)的出现,使得程序员将精力更多放在编写干净、易于维护的代码上,而不是思考如何将每一个CPU时钟、每一字节内存物尽其用。
  • 多核CPU的出现成了“房间里的大象”,无法忽视却没人愿意正视。算法中引入锁不但容易出错,而且消耗时间。人们开发了java.util.concurrent包和很多第三方类库,试图将并发抽象化,用以帮助程序员写出在多核CPU上运行良好的程序。不幸的是,到目前为止,我们走得还不够远。
  • 那些类库的开发者使用Java时,发现抽象的级别还不够。处理大数据就是个很好的例子,面对大数据,Java还欠缺高效的并行操作。Java 8允许开发者编写复杂的集合处理算法,只需要简单修改一个方法,就能让代码在多核CPU上高效运行。为了编写并行处理这些大数据的类库,需要在语言层面上修改现有的Java:增加lambda表达式。
    当然,这样做是有代价的,程序员必须学习如何编写和阅读包含lambda表达式的代码,但是,这不是一桩赔本的买卖。与手写一大段复杂的、线程安全的代码相比,学习一点新语法和一些新习惯容易很多。开发企业级应用时,好的类库和框架极大地降低了开发时间和成本,也扫清了开发易用且高效的类库的障碍。

2. Lambda应用场景及示例

  • 2.1使用() -> {} 替代匿名类
//Before Java 8:
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Before Java8 ");
    }
}).start();
 
//Java 8 way:
new Thread(() -> System.out.println("In Java8!"));

// Before Java 8:
JButton show =  new JButton("Show");
show.addActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
           System.out.println("without lambda expression is boring");
        }
     });
 
// Java 8 way:
show.addActionListener((e) -> {
    System.out.println("Action !! Lambda expressions Rocks");
});
  • 2.2使用内循环替代外循环
List features = Arrays.asList("Lambdas", "Default Method", "Stream API",
 "Date and Time API");
features.forEach(n -> System.out.println(n));

//输出
Lambdas
Default Method
Stream API
Date and Time API

  • 2.3支持函数编程、管道处理数据

Stream:代表通用的引用类型的流式操作接口
IntStream:代表int类型的流式操作接口,避免了int和Integer之间频繁的拆装箱操作
LongStream:代表long类型的流式操作接口,避免了long和Long之间频繁的拆装箱操作
DoubleStream:代表double类型的流式操作接口,避免了double和Double之间频繁的拆装箱操作

可创建Stream的数据源

集合:Collection.stream()或Collection.parallelStream()
数组:Arrays.stream()
对象(或基本数据)序列:Stream.of(),IntStream.of(),LongStream.of(),DoubleStream.of()
字符流:BufferdReader.lines()
文件路径:Files.walk(),Files.lines(),Files.find()
随机数流:Random.ints()
其他:BitSet.stream(),Pattern.splitAsStream(),JarFile.stream()等


示例

  /**
   *
   * Javalambda:使符合条件的String相加
   */
   List strings = Arrays.asList("first","second","third","firefox");
   //strings.forEach(System.out::println);
   String finalString = (String) strings.stream().filter(name-> name.toString().length()<6)
           .collect(Collectors.joining(","));
   System.out.println(finalString);
   //输出
   first,third
 /**
  *
  * 运用Predicate在filter中增加condition
  */
 List strings = Arrays.asList("first","second","third","firefox");
 Predicate<String> startsWithJ = (n) -> n.startsWith("f");
 Predicate<String> fourLetterLong = (n) -> n.length() >= 4;
 strings.stream()
          .filter(startsWithJ.and(fourLetterLong))
          .forEach((n) -> System.out.print(n + " "));
 //输出
 first firefox 
  /**
   *
   * map()函数将stream流中每个对象做相应的改变,reduce()函数将所有值合成一个
   */
  List<BigDecimal> prices = Arrays.asList(new BigDecimal(70),new BigDecimal(80),new BigDecimal(90));
   final BigDecimal totalOfDiscountedPrices = prices.stream()
           .filter(price -> price.compareTo(BigDecimal.valueOf(20)) > 0)
           .map(price -> price.multiply(BigDecimal.valueOf(0.9)))
           .reduce(BigDecimal.ZERO,BigDecimal::add);
   System.out.println("Total of discounted prices: " + totalOfDiscountedPrices);
   //输出
   Total of discounted prices: 216.0
//新方法:get()方法提取Optional中的Integer(实现每个数组加上12再一起相加)
 List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
 int bill = costBeforeTax.stream().map((cost) -> cost + 12).reduce((sum, cost) -> sum + cost).get();
 System.out.println("Total : " + bill);
 //输出
 Total : 1560
 //获取数字的个数、最小值、最大值、总和以及平均值
 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());
 //输出
 Highest prime number in List : 29
Lowest prime number in List : 2
Sum of all prime numbers : 129
Average of all prime numbers : 12.9


二.函数式接口

  • 函数式接口,首先是一个接口,然后就是在这个接口里面只能有一个抽象方法,但是可以有多个非抽象方法的接口。
    Java 8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。
    函数式接口可以被隐式转换为 lambda 表达式。
@FunctionalInterface
interface defaultMethod {
    void apply(String obj);

    default void say(String name) {
        System.out.println("函数式接口中的" + name);
    }
}

public class FuntionalInterfaceTest {
    public static void main(String[] args) {
        defaultMethod i = (o) -> {
            System.out.println("函数式接口中的"+o);
        };
        i.apply("抽象方法");
        i.say("普通方法");
    }
}
//输出
函数式接口中的抽象方法
函数式接口中的普通方法


未完待续更新!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值