一个通俗的说法是 :C#委托和Java中实现了 函数式编程的方法,它是函数式编程中的概念,为了更快的处理集合,在Java,c#等静态类型语言中想要引用一个函数的一种方式,(实现了通过封装匿名方法来达到强类型的链式查询。)
java8中的扩展方法:Java 8 允许我们使用default关键字,为接口
声明添加非抽象的方法实现。这个特性又被称为
扩展方法。
public class defaultMethod { public static void main(String[] args) { Formula formula= new Formula(){ @Override public double calculate( int a){ return sqrt( a*100); } }; formula.calculate(100); // 100.0 formula.sqrt(16); // 4.0 } } interface Formula{ double calculate( int a); default double sqrt(int a){ return Math. sqrt(a); } }
Java8中新加的函数式接口,采用了类似于C#的委托的语法,使得一个方法定义可以直接赋值给一个“函数式接口”,所谓函数式接口就是只包含一个方法定义的接口,可以使用@FunctionalInterface加以约束。引用格式:
1、如果是静态方法,则是
ClassName::methodName。如 Object
::equals
2、如果是实例方法,则是
Instance::methodName。如Object
obj=new Object();obj::equals;
3、构造函数.则是ClassName::new
j a v a 8 提 供 @
FunctionalInterface作为注解,这个注解是非必
须的,只要接口符合函数式接口的标准(即只包
含一个方法的接口),虚拟机会自动判断
示例:
@FunctionalInterface interface Converter<F, T> { T convert(F from); } Converter<String,Integer> converter=(from) ->Integer.valueOf(from ); Integer converted= converter.convert( "123"); System. out.println( converted);
右箭头是java编写lambda的语法糖
扩展:.NET使用ldftn指令获取方法地址,而Java则使用invokedynamic。参见:http://tech.it168.com/a2011/0609/1202/000001202458_2.shtml
.net 使用扩展方法对linq框架(lambda实现框架)进行构建。
而目前java 8的集合框架大量使用了接口中的默认方法来构建了Lambda查询的扩展(java官方解释为兼容性考虑) ,例如:
list接口中
默认方法的实现获取规则:
1.一个声明在类里面的方法优先于任何默认方
法(classes always win)
2.否则,则会优先选取最具体的实现
集合的内部迭代之中间方法与终点方法
java8 Collection接口中新添加的stream方法,可以将任何集合转化为一个Stream,然后通过内部迭代方法进行lambda化的查询。如果你面对的是一个数组,也可以用静态的Stream.of方法将它转化为一个Stream
Filter :在数据流中实现过滤功能
例如:
public static void main(String[] arg){ List<Person> lis= new ArrayList<Person>(); lis.add( new Person(){ }); lis.add( new Person(){ }); lis.add( new Person(){ }); lis.forEach( p-> p.setAge(19)); Stream result=lis.stream().filter(p->p.getAge()>18); }
Map:循环一组元素并返回结果列表 ,其中传入Function<T,R>来作为处理类
例如:
public static void main(String[] arg){ List<Person> lis= new ArrayList<Person>(); Person aa= new Person(); aa.setAge(20); lis.add( aa); // lis.forEach(p->p.setAge(19)); //Stream<Person> result=lis.stream().filter(p->p.getAge()>18); Stream<String> result= lis.stream().map( p-> func(p.getAge())); // Person bb=(Person)result.toArray()[0]; Iterator<String> strIter= result.iterator(); System. out.println( strIter.next()); System. out.println( result.count()); } private static String func( int age) { // TODO Auto-generated method stub return "Age:"+ age; }
count:终点方法,计结果数。
collection:收集最终结果,返回集合结果。
例如:
List<Person> result=lis .stream().collect(Collectors.toCollection(ArrayList::new));
顺序流:List <Person> people = list.getStream.
collect(Collectors.toList());
并行流:List <Person> people = list.getStream.parallel().
collect(Collectors.toList());
顾名思义,当使用顺序方式去遍历时,每个
item读完后再读下一个item。而使用并行去遍历
时,数组会被分成多个段,其中每一个都在不同的
线程中处理,然后将结果一起输出。
扩展:
高阶函数
Lambda表达式除了简化匿名方法的定义以外,由于其强大的表达能力,赋于了语言更多的函数式表达能力。
将参数或者返回类型为函数的函数称为高阶函数。
如斐波那契数列函数定义:
f(0) = 1;
f(1) = 1;
f(n) = f(n-1) + f(n-2);
用C#可以写成:
Func<int, int> f = null;
f = x => x <= 1 ? 1 : f(x - 1) + f(x - 2);
本文参考: