在学习JAVA8 Lambda之前,必须先了解一下JAVA8中与Lambda相关的新特性,不然对于一些概念会感到比较陌生。
1、 接口的默认方法和静态方法 
Java 8允许我们给接口添加一个默认方法,用default修饰即可。默认方法可以重写,也可以不用重写。这就是和抽象方法的区别,在用法上,没有其他区别。
public interface IMyInterface {
    void onMethond(String str);//这是一个抽象方法
    default String onDefalutMethod(){//这是一个默认方法 
        return "这是一个默认方法";
    }
}
//重写默认方法
public class MyImpl1 implements IMyInterface {
    @Override
    public void onMethond(String str) {
        // TODO Auto-generated method stub
    }
    @Override
    public String onDefalutMethod() {
        return "重写默认方法";
    }
}
//不重写默认方法
public class MyImpl2 implements IMyInterface {
    @Override
    public void onMethond(String str) {
        // TODO Auto-generated method stub
    }
}
 
此外Java 8还允许我们给接口添加一个静态方法,用static修饰即可。
public interface IMyInterface {
    void onMethond(String str);//这是一个抽象方法
    default String onDefalutMethod(){//这是一个默认方法 
        return "这是一个默认方法";
    }
    static String onStaticMethod(){
        return "这是一个静态方法";
    }
}2、 函数式接口(Functional Interface) 
什么叫函数式接口?他和普通接口有什么区别? 
“函数式接口”是指仅仅只包含一个抽象方法的接口(可以包含默认方法和静态方法),其他特征和普通接口没有任何区别,Java中Runnalbe,Callable等就是个函数式接口;。我们可以给一个符合函数式接口添加@FunctionalInterface注解,这样就显式的指明该接口是一个函数式接口,如果不是,编译器会直接提示错误。当然你也可以不用添加此注解。添加的好处在于,由于Lambda表达式只支持函数式接口,如果恰好这个接口被应用于Lambda表达式,某天你手抖不小心添加了个抽象方法,编译器会提示错误。
//显式指明该接口是函数式接口
@FunctionalInterface
public interface IMyInterface {
    void onMethond(String str);//这是一个抽象方法
    default String onDefalutMethod(){//这是一个默认方法 
        return "这是一个默认方法";
    }
    static String onStaticMethod(){
        return "这是一个静态方法";
    }
}3、方法与构造函数引用 
Java 8 允许你使用::关键字来引用已有Java类或对象的方法或构造器。::的诞生和Lambda一样都是来简化匿名内部类的写法的,所以::必须配合函数式接口一起用。使用::操作符后,会返回一个函数式接口对象,这个接口可以自己定义,也可以直接使用系统提供的函数式接口,系统提供的后面会单独介绍。请注意,这一节的内容会让你觉得这些用法蛋疼无比,这是因为还没有开始介绍Lambda表达式,::和Lambda结合使用才是王道,希望你还能坚持到介绍Lambda表达式^_^。
假如有个Person类如下,以下的例子都以这个Person类为基础讲解。
public class Person {
    private String name;
    private int age;
    public Person(){
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
   public static String show(String str){
        System.out.println("----->输入"+str);
        return "----->返回"+str;
    }
}
::关键字初始化构造函数,返回的是一个函数式接口,这个接口可以自己定义,也可以直接使用系统提供的函数式接口。现在先来定义一个函数式接口@FunctionalInterface
public interface PersonSupply {
    Person get();
}
PersonSupply sp=Person::new;
Person person=sp.get();PersonSupply sp=Person::new;等价于下面
PersonSupply sp=new PersonSupply{
  public Person get(){
      Person person=new Person();
      return person;
  }
}怎么定义这个函数式接口呢?首先我们要看::后面,可知,默认构造不需要参数,所以我们的get()定义为无参,但是我们需要Person对象,所以返回值为Person。 
当然为了使这个接口更通用,我们可以定义成如下形式
@FunctionalInterface
public interface PersonSupply<T> {
    T get();
}
PersonSupply<Person> sp=Person::new;
Person person=sp.get();java自带Supplier的接口就是这样的,后面会做介绍。直接使用Supplier如下
Supplier<Person> sp=Person::new;
Person person=sp.get();怎么初始化带参构造函数? 
首先写一个函数式接口,由于需要参数所以get()里面输入参数,返回Person,如下。
@FunctionalInterface
public interface PersonSupply<P extends Person> {
    P get(String name, int age);
}
PersonSupply<Person> sp=Person::new;
Person person=sp.get("maplejaw",20);PersonSupply<Person> sp=Person::new;等价于下面
PersonSupply<Person> sp=new PersonSupply<Person>{
  public Person get(String name, int age);{
      Person person=new Person(name,age);
      return person;
  }
}::关键字引用静态方法 @FunctionalInterface
public interface PersonFactory {
    String get(String str);
}
PersonFactory pf=Person::show;
pf.show("哈哈哈");PersonFactory pf=Person::show;等价于下面
PersonFactory pf=new PersonFactory{
  public String get(String str){
      return Person.show(str);
  }
}::关键字引用普通方法比较特殊。 Class::method形式调用,但是这时需要传入一个Person实例,这时函数式接口这样写,在get()中传入Person类的实例,返回String。@FunctionalInterface
public interface PersonFactory {
    String get(Person person);
}
 PersonSupply<Person> sp=Person::new;
 Person person=sp.get("maplejaw", 20);
 PersonFactory pf=Person::getName;      
 System.out.println("--->"+sp.get(penson));PersonFactory pf=Person::getName;等价于下面
PersonFactory pf=new PersonFactory{
  public String get(Person person){
      return person.getName();
  }
}也可以以instance::method形式调用。这时get()不需要传参。返回String。
@FunctionalInterface
public interface PersonFactory {
    String get();
}
 PersonSupply<Person> sp=Person::new;
 Person person=sp.get("maplejaw", 20);
 PersonFactory pf=person::getName;      
 System.out.println("--->"+pf.get());PersonFactory pf=person::getName;等价于下面
Person person=new Person("maplejaw",20);
PersonFactory pf=new PersonFactory{
  public String get( ){
      return person.getName();
  }
}如果要调用的方法有参数,必须用instance::method形式调用,这时函数式接口这样写,set传入参数。
@FunctionalInterface
public interface PersonFactory {
    void set(String name);
}
PersonSupply<Person> sp=Person::new;
Person person=sp.get("maplejaw", 20);
PersonFactory pf=person::setName;
pf.set("maplejaw");PersonFactory pf=person::setName;等价于下面
Person person=new Person("maplejaw",20);
PersonFactory pf=new PersonFactory{
  public void set(String name){
      return person.setName(name);
  }
}4、JAVA8 API内建的函数式接口 
还记得前面提到的Supplier函数式接口吗,它就是API内建的函数式接口之一,下面将介绍一些常用的内建函数式接口。
    Supplier<Person> Supplier=new Supplier<Person>() {
            @Override
            public Person get() {
                return new Person();
            }
        };
    Supplier<Person> sp=Person::new;Function<String, Integer> function=new Function<String, Integer>(){
            @Override
            public Integer apply(String s) {
                return Integer.parseInt(s);
            }
        } ;
Function<String, Integer> function=Integer::parseInt;Consumer<String> consumer=new Consumer<String>() {
            @Override
            public void accept(String t) {
            }
        };        Comparator<Integer> comparator=new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                // TODO Auto-generated method stub
                return o1-o2;
            }
        };Predicate<String> predicate=new Predicate<String>() {
            @Override
            public boolean test(String t) {
                return t.startsWith("h");
            }
        };
boolean b=predicate.test("hahaha");//判断是否符合条件Predicate<String> predicate = String::isEmpty;
boolean b=predicate.test("hahaha");//判断是否符合条件    UnaryOperator<String> unaryOperator=new UnaryOperator<String>() {
            @Override
            public String apply(String s) {
                // TODO Auto-generated method stub
                return s;
            }
        };BinaryOperator<String> binaryOperator=new BinaryOperator<String>() {
            @Override
            public String apply(String t, String u) {
                // TODO Auto-generated method stub
                return t+u;
            }
        };5、三个API
Optional<String> optional = Optional.of("给你一个值");
        optional.isPresent(); //判断是否为空值
        optional.get();      //获取值 ,如果空值直接抛异常。
        optional.orElse("返回空值");  //获取值 ,如果空值返回指定的值。Stream(流) 
最新添加的Stream API(java.util.stream)把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。 
接触过RxJava的可能对下面的代码风格比较眼熟,Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, Map不支持。Stream的操作可以串行执行或者并行执行。 
怎么用Stream?Stream必须有数据源。那就给一个数据源。
List<String> list = new ArrayList<>();
    list.add("ddd2");
    list.add("aaa2");
    list.add("bbb1");
    list.add("aaa1");
    list.add("aaa3");
    list.add("bbb3");
    list.add("ccc");
    list.add("bbb2");
    list.add("ddd1");forEach list新增的for循环方法,forEach是一个最终操作(只能放在最后)
//遍历打印数据
list.forEach(new Consumer<String>() {
            @Override
            public void accept(String t) {
             System.out.println("---->"+t);
            }
        });打印结果如下
---->ddd2
---->aaa2
---->bbb1
---->aaa1
---->aaa3
---->bbb3
---->ccc
---->bbb2
---->ddd1
filter 过滤
list.stream()
   .filter(new Predicate<String>() {
            @Override
            public boolean test(String t) {
                return t.startsWith("a");
            }
        })
    .forEach(new Consumer<String>() {
            @Override
            public void accept(String t) {
             System.out.println("---->"+t);
            }
        });打印结果如下
---->aaa2
---->aaa1
---->aaa3
Sort 排序
 list.stream()
        .sorted()//排序,如果不实现Comparator接口,则按默认规则排序
         .filter(new Predicate<String>() {
            @Override
            public boolean test(String t) {
                return t.startsWith("a");
            }
        })
         .forEach(new Consumer<String>() {
            @Override
            public void accept(String t) {
             System.out.println("---->"+t);
            }
        });
    list.stream()
         .sorted(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // TODO Auto-generated method stub
                return o1.compareTo(o2);
            }
        })
         .filter(new Predicate<String>() {
            @Override
            public boolean test(String t) {
                return t.startsWith("a");
            }
        })
         .forEach(new Consumer<String>() {
            @Override
            public void accept(String t) {
             System.out.println("---->"+t);
            }
        });map
     list.stream()
        .sorted(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // TODO Auto-generated method stub
                return o1.compareTo(o2);
            }
        })
         .filter(new Predicate<String>() {
            @Override
            public boolean test(String t) {
                return t.startsWith("a");
            }
        })
         .map(new Function<String, String>() {
            @Override
            public String apply(String t) {
                // TODO Auto-generated method stub
                return t+"--->被我处理过了";
            }
        })
         .forEach(new Consumer<String>() {
            @Override
            public void accept(String t) {
             System.out.println("---->"+t);
            }
        });
---->aaa1--->被我处理过了
---->aaa2--->被我处理过了
---->aaa3--->被我处理过了Match 匹配,是一个最终操作
boolean b= list.stream()
            .anyMatch(new Predicate<String>() {
                @Override
                public boolean test(String t) {
                    // TODO Auto-generated method stub
                    return t.startsWith("a");
                }
            });
    System.out.println("----->"+b);//true
    boolean b= list.stream()
            .allMatch(new Predicate<String>() {
                @Override
                public boolean test(String t) {
                    // TODO Auto-generated method stub
                    return t.startsWith("a");
                }
            });
    System.out.println("----->"+b);//falseCount 计数,是一个最终操作
long count = list.stream()
              .filter(new Predicate<String>() {
                    @Override
                    public boolean test(String t) {
                        return t.startsWith("a");
                    }
                })
              .count();
        System.out.println(count);    // 3
Reduce 规约,最终操作
     Optional<String> optional = 
                list
                    .stream()
                     .sorted()
                    .reduce(new BinaryOperator<String>() {
                        @Override
                        public String apply(String t, String u) {
                            return t+u;
                        }
                    });
     System.out.println("---->"+optional.get());
     //---->aaa1aaa2aaa3bbb1bbb2bbb3cccddd1ddd2findFirst 提取第一个,最终操作
 Optional<String> optional = 
                list
                    .stream()
                     .sorted()
                    .findFirst();
     System.out.println("---->"+optional.get()); //aaa1
parallelStream(并行流) 
并行化之后和之前的代码区别并不大。并且并行操作下,速度会比串行快。但是需要注意的是不用在并行流下排序,并行流做不到排序。
 list.parallelStream()
            .filter(new Predicate<String>() {
                @Override
                public boolean test(String t) {
                    // TODO Auto-generated method stub
                    return t.startsWith("a");
                }
            })
            .forEach(new Consumer<String>() {
                @Override
                public void accept(String t) {
                    // TODO Auto-generated method stub
                    System.out.println("--->"+t);
                }
            });
    list.parallelStream()
            .sorted()
            .forEach(new Consumer<String>() {
                @Override
                public void accept(String t) {
                    // TODO Auto-generated method stub
                    System.out.println("--->"+t);
                }
            });
            //打印出来的并没有排序在上面你是不是觉得::有时候挺好用的?可以不用再new接口,再也不用写烦人的匿名内部类了,比如
    Supplier<Person> sp=Person::new;但是::的使用场景还是比较有限的。Lambda表达式的诞生就是为了解决匿名内部类中饱受诟病的问题的。
什么是Lambda表达式 
Lambda表达式是Java8的一个新特性,它提供了一种更加清晰和简明的方式使用函数式接口(以前被叫作单一方法接口)。使用Lambda表达式能够更加方便和简单的使用匿名内部类,比如对于集合的遍历、比较、过滤等等。
Lambda表达式格式 
(type1 arg1, type2 arg2…) -> { body } 
每个lambda都包括以下三个部分: 
参数列表:(type1 arg1, type2 arg2…) 
箭头:    ->  
方法体:{ body }
方法体既可以是一个表达式,也可以是一个语句块:
以下是一些例子
(int a, int b) -> {  return a + b; }
( a,  b) -> {  return a + b; }
( a,  b) -> a+b
() -> System.out.println("s")
(String s) -> { System.out.println(s); }Lambda表达式可以用来简化内部类写法,比如
   //常规代码
   Runnable runable=new Runnable() {
        @Override
        public void run() {
            System.out.println("--->");
        }
    };
    //Lambda表达式
    Runnable runable=()->{System.out.println("--->");};
    //启动一个线程
    new Thread(()->{System.out.println("--->");}).start();还记得前面介绍的Predicate接口吗?现在我们再来用Lambda表达式写一遍。
//一般写法
Predicate<String> predicate=new Predicate<String>() {
            @Override
            public boolean test(String t) {
                return t.startsWith("h");
            }
        };
//Lambda写法
Predicate<String> predicate=(String s)->{s.startsWith("h");};你现在是不是觉得Lambda表达式太神奇了?居然可以写出这么简洁的代码。 
还记得内部类使用局部变量时需要把变量声明为final吗,Lambda表达式则不需要。不过虽然不用声明final,但也不允许改变值。
        String s="sss";
        new Thread(()->{
            System.out.println(s);
        }).start();此外,内部类引用外部类也不用使用MainActivity.this,这种操蛋的代码了。 
在Lambda表达式中this,指的就是外部类,因为根本就没有内部类的概念啊。
  btn.setOnClickListener(()->{
            Toast.makeText(this,"xxx",Toast.LENGTH_SHORT).show();
        });现在回过头来把前面Stream中的代码用Lambda表达式再写一遍。
         list.stream()
             .sorted((s1,s2)->s1.compareTo(s2))
             .filter((s)->s.startsWith("a"))
             .map((s)->s+"被我处理过了")
             .forEach(s->System.out.println(s));代码简洁的简直让人窒息。但是能不能更简洁一点呢?当然是可以的,首先我们检查一下哪里可以替换成::关键字,然后作如下替换,是不是更简洁了。关于替换规则,请看前面的介绍。
 list.stream()
            .sorted((s1,s2)->s1.compareTo(s2))
             .filter((s)->s.startsWith("a"))
             .map((s)->s+"被我处理过了")
             .forEach(System.out::println);打印结果如下
aaa1被我处理过了
aaa2被我处理过了
aaa3被我处理过了//接口一
public interface IMyInterface1 {
    void opreate(String str);
}
//接口二
public interface IMyInterface2 {
    void opreate(int i);
}
//Person类
public class Person类 {
    private String name;
    private int age;
    public Test(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void opreate(IMyInterface1 inter){
        inter.opreate(name);
    }
    public void opreate(IMyInterface2 inter){
        inter.opreate(age);
    }
}
 //这样写是错误的,因为编译器无法推导出其目标类型
  new Test("maplejaw",20).opreate((name)->System.out.println(name));
解决办法有两个 
一、指定参数类型,但是如果两个接口的参数类型是一样的,就只能显示指定目标类型。
  new Test("maplejaw",20).opreate((String name)->System.out.println(name));二、指定目标类型
  new Test("maplejaw",20).opreate((IMyInterface1) (s)->System.out.println(s));
  new Test("maplejaw",20).opreate((IMyInterface1) System.out::println);由于目标类型必须是函数式接口,所以如果想赋值给Object对象时,也必须显示转型。
Object runnable=(Runnable)()->{System.out.print("--->");};关于Lambda表达式的介绍到此为止,想更深入了解推荐【深入理解Java 8 Lambda】这篇文章。
当初学习Lambda表达式的时候,由于网上的资料比较零散,且直接用了JAVA8的新API来做演示,由于对新API不是很熟导致学习的时候走了一些弯路,看得一头雾水。所以决定把我的学习路线给记录下来,或许可以帮助部分人。 
Lambda表达式是把双刃剑,让代码简洁的同时,降低了代码的可读性。但是作为程序员,追逐新技术的脚步不能停下。
本文参考了【深入理解Java 8 Lambda】和【JAVA8 十大新特性详解】两篇文章
原文:http://blog.csdn.net/maplejaw_/article/details/51348162