黑马程序员技术交流社区

标题: [重庆校区]JAVA8 新特性 lambda [打印本页]

作者: oracle0326    时间: 2017-9-13 10:21
标题: [重庆校区]JAVA8 新特性 lambda
本帖最后由 oracle0326 于 2017-9-13 10:27 编辑

       JAVA8已经发布有好几年了,国内大部分项目目前还使用的1.8,现在JAVA9也快发布了,按照国内项目的惯性,很快也快换上JDK1.8.       乘着这段空谷期,我们来回顾一下JAVA8的一个重大的更新 lambda 表达式.
       可以说 lambda 的引入,是JAVA的又一里程碑.大大简化了JAVA语言开发,只有这样不断的吸收其他语言优点JAVA才能长盛不衰.
       对于JAVA程序员来说,从面对对象的一个思维方式转换成函数式编程这么一个“全新”的思维模式,是一个不小的学习成本.不过相对于他的优点这些就微不足道了.
       我们先看个例子,从第一行开始计时,看你需要多久来读懂他,
      
[Java] 纯文本查看 复制代码
List<String> names = Arrays.asList("张三", "李四", "王五", "李白", "王居易", "李商隐");
List<String> subList = new ArrayList<>();
for(String name : names) {
  if(name.length() == 2)
    subList.add(name);
}

StringBuilder namesOfLength4 = new StringBuilder();
for(int i = 0; i < subList.size() - 1; i++) {
  namesOfLength4.append(subList.get(i));
  namesOfLength4.append(", ");
}
        
if(subList.size() > 1)
  namesOfLength4.append(subList.get(subList.size() - 1));

System.out.println(namesOfLength4);
     理解此代码需要多少时间?如果时间比您预计的要长,不要惊讶。
   同样 我们来看下lambda 表达式的一个写法:
  
[Java] 纯文本查看 复制代码
List<String> names = Arrays.asList("张三", "李四", "王五", "李白", "王居易", "李商隐");
         
System.out.println(
  names.stream()
    .filter(name -> name.length() == 2)
    .collect(Collectors.joining(", ")));
同样的理解此代码需要多少时间?就算你不懂lambda 表达式,可能理解这段代码也不费劲.从集合里面,过滤出长度为2的人名,并用, ","拼接.
简洁,易懂,高效就是函数式编程的魅力.
下面我们先来看下 lambda 表达式常用的一些写法:
[Java] 纯文本查看 复制代码
(int x, int y) -> x + y

() -> 42

(String s) -> { System.out.println(s); }

第一个lambda表达式接收x和y这两个整形参数并返回它们的和;
第二个lambda表达式不接收参数,返回整数42;
第三个lambda表达式接收一个字符串并把它打印到控制台,不返回值。
lambda表达式的语法由参数列表、箭头符号->和函数体组成。函数体既可以是一个表达式,也可以是一个语句块:
表达式:表达式会被执行然后返回执行结果。
语句块:语句块中的语句会被依次执行,就像方法中的语句一样。
return语句会把控制权交给匿名方法的调用者
break和continue只能在循环中使用
如果函数体有返回值,那么函数体内部的每一条路径都必须返回值.

我们再来看看几个例子:
[Java] 纯文本查看 复制代码
// 1. 不需要参数,返回值为 5
() -> 5

// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x

// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y

// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y

// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
再来看几个复杂一点的,我们来改写一个for循环:
[Java] 纯文本查看 复制代码
String[] atp = {"Rafael Nadal", "Novak Djokovic",
       "Stanislas Wawrinka",
       "David Ferrer","Roger Federer",
       "Andy Murray","Tomas Berdych",
       "Juan Martin Del Potro"};
List<String> players =  Arrays.asList(atp);

// 以前的循环方式
for (String player : players) {
     System.out.print(player + "; ");
}

// 使用 lambda 表达式以及函数操作(functional operation)
players.forEach((player) -> System.out.print(player + "; "));

// 在 Java 8 中使用双冒号操作符(double colon operator)
players.forEach(System.out::println);

匿名类也可以使用lambda表达式来代替:
[Java] 纯文本查看 复制代码
// 1.1使用匿名内部类
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello world !");
    }
}).start();

// 1.2使用 lambda expression
new Thread(() -> System.out.println("Hello world !")).start();

// 2.1使用匿名内部类
Runnable race1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello world !");
    }
};

// 2.2使用 lambda expression
Runnable race2 = () -> System.out.println("Hello world !");

// 直接调用 run 方法(没开新线程哦!)
race1.run();
race2.run();

当然并不是所有的lambda都是好的写法,找出英文名字中 以 "J" 开头,长度为3个字的,并把名字转换成大写以","拼接输出.
[Java] 纯文本查看 复制代码
System.out.println(names.stream().filter(name -> name.startsWith("J")).filter(name -> name.length() > 3)
  .map(name -> name.toUpperCase()).collect(Collectors.joining(", ")));

这两行代码,精简但是不不易读,因为他包含了多个函数 有filter map .....
所以在这儿精简行数没有意义,JAVA 8 有约定 对齐函数组合的垂直方向上的各点.


[Java] 纯文本查看 复制代码
System.out.println(
names.stream()
      .filter(name -> name.startsWith("J"))
      .filter(name -> name.length() > 3)
      .map(name -> name.toUpperCase())
      .collect(Collectors.joining(", ")));


JAVA8 除了lambda 还有很多重大的更新,这里就不一一累述了,大家有兴趣去收一下相关的文档


   






作者: Oliverwqcwrw    时间: 2017-9-14 09:16
6666666666666666




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2