参考资料:java
《Java8 in Action》 Raoul-Gabriel Urmapython
客观的说,Java8是一次有重大演进的版本,甚至不少人认为java8所作的改变,在许多方面都比Java历史上任何一次改变都深远。编程
Scala,python这样优秀编程语言中对函数式编程的处理,guava中的理念等等....设计模式
java8的代码更简洁...并发
java8对并发编程更加友好,java一直努力让并发编程更为高效,出错更少,jdk1.0里有线程和锁,Java 5增长的工业模块,Thread pools和一大堆并发工具类, Java7增长了fork/join框架,Java8则对并行提供了一个新的思路app
新的API,例如Stream等 框架
等等编程语言
首先有一个苹果类ide
public static class Apple { private int weight = 0; private String color = ""; public Apple(int weight, String color){ this.weight = weight; this.color = color; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String toString() { return "Apple{" + "color='" + color + '\'' + ", weight=" + weight + '}'; } }
须要2个函数以供过滤出须要的苹果函数式编程
public static List<Apple> filterApplesByColor(List<Apple> inventory, String color){ List<Apple> result = new ArrayList<Apple>(); for(Apple apple: inventory){ if(apple.getColor().equals(color)){ result.add(apple); } } return result; } public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight){ List<Apple> result = new ArrayList<Apple>(); for(Apple apple: inventory){ if(apple.getWeight() > weight){ result.add(apple); } } return result; }
上面的代码比较啰嗦,并且若是还有新的需求,依旧须要添加新的方法,之前的java实现函数就是静态方法。
Java中封装行为的方式只能经过匿名类之类的方式。首先定义一个接口:
interface ApplePredicate{ public boolean test(Apple a); }
因而方法变为:
public static List<Apple> filter(List<Apple> inventory, ApplePredicate p){ List<Apple> result = new ArrayList<Apple>(); for(Apple apple : inventory){ if(p.test(apple)){ result.add(apple); } } return result; }
在以前的java,用以下方式:
static class AppleWeightPredicate implements ApplePredicate{ public boolean test(Apple apple){ return apple.getWeight() > 150; } } static class AppleColorPredicate implements ApplePredicate{ public boolean test(Apple apple){ return "green".equals(apple.getColor()); } }
2个新的实现类,从设计模式上是策略模式... 能够更灵活的扩展,可是感受代码更啰嗦了...
固然你也能够不定义出类,使用匿名内部类,仍是很啰嗦.
List<Apple> redApples2 = filter(inventory, new ApplePredicate() { public boolean test(Apple a){ return a.getColor().equals("red"); } });
List<Apple> result = filter(inventory ,(Apple apple)-> "red".equals(apple.getColor()));
jdk8中再进一步将Perdicate抽象为泛型类...
public interface Predicate<T> { boolean test(T var1); //.... }
不少语言都支持lambda,例如python,能够把lambda表达式简单理解为表示可传递的匿名函数的一种方式: 它没有名称,可是有参数列表、函数主题、返回类型,可能还有一个异常列表.
让咱们来改造一段代码...
Comparator<Apple> byWeight = new Comparator<Apple>() { @Override public int compare(Apple o1, Apple o2) { return o1.getWeight().compareTo(o2.getWeight()); } }; Comparator<Apple> byWeight2 = (Apple a1, Apple a2) -> a1.getWeight() - a2.getWeight();
(Apple a1, Apple a2) 是Lambda的参数列表,加上一个小箭头,加上主体 a1.getWeight() - a2.getWeight()
(params) -> experssion
(params) -> {statements;}
举例:
(1) () -> {};
(2) () -> "Raoul"
(3) () -> {return "aaa";}
(4) (int i) -> return "Al" + 1;
(5) (String s) -> {"IronMan";}
上述中只有(4), (5) 不符合语法,(4)的主体是statements;须要用{},(5)的主体是statements,所以不能使用{}...
函数是接口就是只定义了一个抽象方法的接口。 jdk8中接口还能够定义默认方法,哪怕有不少的默认方法,可是只要接口只定义了一个抽象方法,它就仍然是一个函数式接口。
Lambda容许你把lambda表达式做为函数式接口的一个实现的实例
MyInteface myInteface = (int i, int j) -> i+j; System.out.println(myInteface.add(1,2)); public interface MyInteface{ int add(int i, int j); }
函数式接口中有且只有一个方法,这个方法的签名就是lambda表达式的签名。这种抽象方法叫作函数描述符...
@FuntionalInterface?
接口标注,表示接口会被设计为一个函数式接口。按照官方说法就是:
java.util.function包中引入了经常使用的函数式接口
public static <T> List<T> filte(List<T> list, Predicate<T> p){ List<T> results = new ArrayList<T>(); for (T t : list) { if (p.test(t)) results.add(t); } return results; }
Predicate中还有一些add, not等默认方法,暂不讨论...
其中定义了一个accept()方法,没有返回值
public static <T> void forEach(List<T> list, Consumer<T> c){ for (T i : list) { c.accept(i); } } public static void main(String[] args) { forEach( Arrays.asList(1,2,3,4,5), (Integer i) -> { System.out.println(i); } ); }
相似于Guava的Function,定义了一个apply的方法,例子中打印每一个字符串的长度...
public static <T, R> List<R> map(List<T> list, Function<T, R> f){ List<R> result = new ArrayList<R>(); for (T t : list) { result.add(f.apply(t)); } return result; } public static void main(String[] args) { List<Integer> l = map( Arrays.asList("lambdas","in","action"), (String s) -> s.length() ); System.out.println(l); }
自从jdk1.5以后就支持自动装箱inbox,但装箱以后好比将一个原始类型转换成了Integer,在heap划分一块内存分配等等,IntPredicate能够避免无谓的装箱..
IntPredicate evenNumbers = (int i) -> i%2 ==1; Predicate<Integer> predicate = (Integer i) -> i%2 ==1;
也能够说由于泛型每每不能使用基本类型
方法引用能够被看作仅仅调用特定Lambda的一种快捷写法。例如
(Apple a) -> a.getWeight() 能够写成 Apple::getWeight
() -> Thread.currentThread.dumpStack() 能够写成 Thread.currentThread()::dumpStack
(str, i) -> str.substring(i) 能够写成 String:substring
(Sring s) -> System.out.println(s) 能够写成 System.out::println
(1) 静态方法,类的方法,例如Interger的parseInt Interger::parseInt
(2) 实例方法, String::length
(3) 指向现有方法的方法引用: expensiveTransaction::getValue
使用Lambda表达式的用法
public static void main(String[] args) { Comparator<String> comparator = (String s1,String s2) -> s1.compareToIgnoreCase(s2); List<String> l = Arrays.asList("a","b","A","B"); Collections.sort(l,comparator); System.out.println(l); }
可换成:
Comparator<String> comparator = String::compareToIgnoreCase; List<String> l = Arrays.asList("a","b","A","B"); Collections.sort(l,comparator); System.out.println(l);
public static void main(String ... args){ List<Apple> inventory = new ArrayList<>(); inventory.addAll(Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red"))); //1. 使用逆序 inventory.sort( Comparator.comparing(Apple::getWeight).reversed() ); //2. 比较器链 inventory.sort( Comparator.comparing(Apple::getWeight).reversed().thenComparing(Apple::getColor) ); }
比较器链中若是重量相同,就按颜色排序...
public static void main(String ... args){ Predicate<Apple> redApple = (Apple a) -> "red".equals(a.getColor()); Predicate<Apple> notRedApple = redApple.negate(); Predicate<Apple> redAndHeavyApple = redApple.and(a -> a.getWeight()>150); Predicate<Apple> readAndHeavyOrGreenApple = redApple.and(a -> a.getWeight()>150).or(a -> "green".equals(a.getColor())); }
以Function为例,实现相似于g(f(x))和f(g(x))的效果
public static void main(String... args) { Function<Integer, Integer> f = x -> x + 1; Function<Integer, Integer> g = x -> x * 2; Function<Integer, Integer> h = f.andThen(g); Function<Integer, Integer> k = f.compose(g); System.out.println(h.apply(3)); System.out.println(k.apply(3)); }