java8中Lambda表达式和Stream API

java8中Lambda表达式和Stream API

 

1、Lambda表达式

1.语法格式

Lambda是匿名函数,能够传递代码。使用“->”操做符,改操做符将lambda分红两部分:html

左侧:指定了 Lambda 表达式须要的全部参数java

右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能,也就是实现接口方法的代码数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 语法格式一:无参、无返回值  
@Test  
public void test1() {  
     Runnable runable = () -> System.out.println("hello lambda!");  
     runable.run();  
}  
   
// 语法格式二:有一个参、无返回值  
@Test  
public void test2() {  
     Consumer< String > consumer = (args) -> System.out.println("hello!"  
            + args);  
     consumer.accept("lambda");  
}  
   
// 语法格式三:有多个参、有返回值,而且有多条执行语句,用大括号包围  
@Test  
public void test3() {  
    Comparator< Integer > com = (x, y) -> {  
        System.out.println("hello lambda!");  
        return Integer.compare(x, y);  
     };  
     int rs = com.compare(2, 2);  
     System.out.println(rs);  
}  
   
// 语法格式四:右侧若是只有一条执行语句,能够省略大括号和return  
@Test  
public void test4() {  
    Comparator< Integer > com = (Integer x, Integer y) -> Integer.compare(x, y);  
    int rs = com.compare(2, 2);  
    System.out.println(rs);  
}  

注:lambd能够省略接口参数类型,java编译器会根据上下文进行类型推断数组

2.函数式接口

(1)只包含一个抽象方法的接口,称为函数式接口,能够在任意函数式接口上使用 @FunctionalInterface 注解,lambda须要函数式接口的支持。app

(2)java8内置四大核心函数式接口:dom

Consumer<T>消费型接口:void accept(T t)函数

1
2
3
4
5
6
@Test  
public void test2() {  
     Consumer< String > consumer = (args) -> System.out.println("hello!"  
            + args);  
     consumer.accept("lambda");  
}  

Supplier<T>供给型接口:T get()post

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void test5() {
     List< Integer > rs=getNumList(6,() -> (int)(Math.random()*100));
     System.out.println(rs);
}
 
public List< Integer > getNumList(int size,Supplier< Integer > sup){
     List< Integer > list=new ArrayList< Integer >();
     for (int i = 0; i < size; i++) {
         Integer e=sup.get();
         list.add(e);
     }
    return list;
}

Function<T, R>函数型接口:R apply(T t)spa

1
2
3
4
5
6
@Test  
public void test6() {  
     Function< String , Integer> fun=(str)->str.length();  
     int len=fun.apply("lambda");  
     System.out.println(len);  
}  

Predicate<T>判定型接口:boolean test(T t)code

1
2
3
4
5
6
@Test  
public void test7() {  
     Predicate< String > check=(str)->str.equals("lambda");  
     boolean rs=check.test("lambda");  
     System.out.println(rs);  
}  

3.方法引用

当要传递给Lambda体的操做,已经有实现的方法了,能够使用方法引用!( lambda要实现抽象方法的参数列表,必须与方法引用的方法参数列表保持一致! )。
方法引用:使用操做符 “ ::” 将对象或类和方法的名字分隔开来。

三种主要使用状况:

对象::方法名

1
2
3
PrintStream ps=System.out;  
Consumer< String > consumer =  ps::println;  
consumer.accept("lambda");

类::静态方法名

1
2
3
Comparator< Integer > com = Integer::compare;  
int rs = com.compare(2, 2);  
System.out.println(rs);  

类::实例方法名(前提条件:lambda参数列表的第一个参数是实例方法的调用者,第二个参数是实例方法的入参)

1
2
BiPredicate< String ,String> check=(str1,str2)->str1.equals(str2);  
BiPredicate< String ,String> check1=String::equals;  

4.构造器引用

与函数式接口相结合,自动与函数式接口中方法兼容(须要调用的构造器方法参数列表要与函数式接口中方法的参数列表一致)

格式: ClassName::new

5.数组引用

格式: type[] :: new

2、Stream API

1.说明解释

Stream 是 Java8 中处理集合的关键抽象概念,它能够指定你但愿对集合进行的操做,能够执行很是复杂的查找、过滤和映射数据等操做。使用Stream API 对集合数据进行操做,就相似于使用 SQL 执行的数据库查询。也能够使用 Stream API 来并行执行操做。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。流(Stream)是数据渠道,用于操做数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,流讲的是计算! ”

注意:
①Stream 本身不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操做是延迟执行的。这意味着他们会等到须要结果的时候才执行。

2.Stream 操做步骤

(1)建立Stream

①能够经过Collection系列集合提供的stream()或者parallelStream()得到

1
2
List< String > list=new ArrayList< String >();  
Stream< String > stream=list.stream();  

②能够经过Arrays的静态方法stream()得到数组流

1
2
Person[] ps=new Person[10];  
Stream< Person > stream=Arrays.stream(ps); 

③能够经过Stream的静态of()

1
Stream< String > steam=Stream.of("aa","bb","cc"); 

④能够使用静态方法 Stream.iterate() 和Stream.generate(), 建立无限流

(2)中间条件操做

说明:多个中间操做能够链接起来造成一个流水线,除非流水线上触发终止操做,不然中间操做不会执行任何的处理!而在终止操做时一次性所有处理,称为“惰性求值”。

①筛选与切片
        filter——接收 Lambda , 从流中排除某些元素。
        limit——截断流,使其元素不超过给定数量。
        skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
        distinct——筛选去重,经过流所生成元素的 hashCode() 和 equals() 去除重复元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
List< Person > personList = Arrays.asList(  
                 new Person("李四", 20, 10),  
                 new Person("张三", 40,30),  
                 new Person("王五", 28, 15),  
                 new Person("赵六", 60, 60),  
                 new Person("赵六", 60, 60),  
                 new Person("赵六", 60, 60),  
                 new Person("田七", 8,2)  
         );  
           
         Stream< Person > stream=personList.stream();          
         stream.filter((p)->p.getAge()>20)//过滤保留age>20  
         .limit(5)//只取前两个  
         .skip(1)//跳过前一个,返回剩下的  
         .distinct()//去重,自动定义对象去重要重写equals和hashcode  
         .forEach(System.out::println); 

②映射
        map——接收 Lambda,将元素转换成其余形式或提取信息。接收一个函数做为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素。
        flatMap——接收一个函数做为参数,将流中的每一个值都换成另外一个流,而后把全部流链接成一个流

1
2
3
Stream< Person > stream=personList.stream();          
stream.map((p)->p.getName())//提取name,组成新的Stream流  
          .forEach(System.out::println);  

③排序
        sorted()——天然排序(Comparable)
        sorted(Comparator com)——定制排序

(3)执行操做

查找与匹配        allMatch——检查是否匹配全部元素,返回boolean        anyMatch——检查是否至少匹配一个元素,返回boolean        noneMatch——检查是否没有匹配的元素,返回boolean        findFirst——返回第一个元素        findAny——返回当前流中的任意一个元素        count——返回流中元素的总个数        max——返回流中最大值        min——返回流中最小值

相关文章
相关标签/搜索