Java8之Lambda表达式基础
Java 8中,将会提供对lambda的支持,函数式编程FP(Functional Programming)将会得到很好地支持,而函数式编程的一个重要特点就是适合并行运算。
λ:希腊字母表中排序第十一位的字母,英语名称为Lambda,读音:兰亩达。
语法如下:
(parameters) -> expression
(parameters) -> statement
(parameters) -> {statements;}
例子如下:
() -> Math.PI * 2.0
(int i) -> i * 2
(String s) -> s.length()
(int i0, int i1) -> i0 + i1
(int x, int y) -> { return x + y; }
更多的特性:
一、省略参数类型
(int x, int y) -> { return x + y; };
可以省略参数类型,写成(x, y) -> { return x + y; };
不能只省略一部分类型,比如:(int x, y) -> { return x + y; }; //error
二、1个参数可以省略括号
(String text) -> { System.out.println(text); };
可以写为:(text) -> { System.out.println(text); };
也可以写为: text -> { System.out.println(text); };
但是不能带类型,比如:String text -> { System.out.println(text); }; //error
三、函数体多行时需要大括号
(int i) -> {
int prod = 1;
for(int n = 0; n < 5; n++) prod *= i;
return prod;
};
四、函数体只有一行时有些情况下可以省略大括号
text -> System.out.println(text);
注:assert语句不能省略带括号,比如: s -> { assert !s.isEmpty(); };
注:return语句不能省略带括号,比如:(x, y) -> return x -y; //error
五、只有一行代码而且有返回值的可以省略return,会返回该行代码计算结果
(x, y) -> { return x -y; };
(x, y) -> x -y;
注:return要和大括号一起省略,比如:(x, y) -> { x – y; }; //error
六、用于Lambda的变量不可变
int portNumber = 1337; Runnable r = () -> System.out.println(portNumber); // OK // 编译错误 // Local variable portNumber defined in an enclosing scope must be final or effectively final int portNumber = 1337; Runnable r = () -> System.out.println(portNumber); // NG portNumber = 1338; // 通过数组实现 final int[] wrappedNumber = new int[] { 1337 }; Runnable r = () -> System.out.println(wrappedNumber[0]); // OK wrappedNumber[0] = 1338;
Lambda可以传递给任何希望是函数式接口的地方,比如遍历List:
Arrays.asList(“a”, “b”, “c”).forEach(x -> System.out.println(x));
也可以接住异常堆栈信息看看Lambda是怎么执行的:
String[] datas = new String[]{""}; Arrays.asList(datas).stream().forEach(name -> check(name)); public static int check(String s) { if (s.equals("")) { throw new IllegalArgumentException(); } return s.length(); }
Java 8 的类库包含一个新的包 java.util.functions ,这个包中有很多新的功能接口,这些接口可与集合类一起使用。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave"); List<String> filteredNames = names .filter(e -> e.length() >= 4) .into(new ArrayList<String>()); for (String name : filteredNames) { System.out.println(name); }
上述的例子还可以写为:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave"); names .filter(e -> e.length() >= 4) .forEach(e -> { System.out.println(e); });
一段代码这样写:
// 求一个List中的最大值 public static void main(String[] args) { List<Integer> k = new ArrayList<Integer>(); k.add(1); k.add(2); k.add(3); k.add(8); k.add(11); k.add(20); k.add(50); int max = Integer.MIN_VALUE; for (int j : k) { if (max < j) { max = j; } } System.out.println(max); }
假如这段代码中查找最大值成了性能瓶颈,那么需要将这段代码改为并发操作。想想就不容易。那现在使用lamda表达式这样写:
// 求一个链表中的最大值 public static void main(String[] args) { List<Integer> k = new ArrayList<Integer>(); k.add(1); k.add(2); k.add(3); k.add(8); k.add(11); k.add(20); k.add(50); Optional<Integer> max = k.stream().max((a,b) -> {return a-b;}); System.out.println(max); }
想变成并发操作这样写:
// 求一个链表中的最大值 public static void main(String[] args) { List<Integer> k = new ArrayList<Integer>(); k.add(1); k.add(2); k.add(3); k.add(8); k.add(11); k.add(20); k.add(50); Optional<Integer> max = k.parallelStream().max((a,b) -> {return a-b;}); System.out.println(max); }
很简单吧。就是将k.stream() 改成 k.parallelStream()
详细的可以参考:http://blog.csdn.net/cctt_1/article/details/24835803