17、lambda表达式
一、简介
lambda表达式允许你通过表达式来代替功能接口,lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块),它还增强了集合库,java.util.function包java.util.stream包
流就如同迭代器,但附加了许多额外的功能。
二、基本语法
(parameters)->expression
或
(parameters)->{statements;}
例子:输出的->代表一个Consumer接口用来接收一个输入对象并处理,如果需要访问类型T的对象,并对其执行某些操作,就可以使用这个接口。
public class A { public static void main(String[] args) { IA i=(int c,int d)-> System.out.println(c); i.run(100,200); } } interface IA{ public void run(int a,int b); }
三、例子
遍历数组(数组变成列表,使用列表的forEach方法遍历,其中System.out::println用来输出当前调用它的对象内容)
public class B { public static void main(String[] args) { String names[]={"JAKE","MIKE","ROSE"}; List<String> list= Arrays.asList(names);//数组变成list list.forEach(n-> System.out.println(n)); list.forEach(System.out::println); } }
字符数组排序,—>代表Comparator接口用来比较字符串
public class C { public static void main(String[] args) { String names[]={"MIKE","JAKE","ROSE"}; Arrays.sort(names,(String s1,String s2)->s1.compareTo(s2)); List<String> list=Arrays.asList(names); list.forEach(System.out::println); } }
四、Lambda内置函数接口和Stream和parallelStream操作(并行流)
Stream(这个Stream不是之前那个流,而是lambda下的流)是对集合的包装,通常和lamabda一起使用,是java8的新特性,它不是集合元素,不是数据结构,并不保存数据,它是有关算法和计算的,它更像一个高级版本的Iterator。原始版本的Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的Stream,用户只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,Stream会隐式的在内部进行遍历,做出相应的数据转换。Stream就如同一个迭代器:单向,不可重复,数据只能遍历一次,遍历过一次后即用尽了。
Stream和迭代器不同点:Stream可以支持并行化操作,迭代器只能命令式、串行化操作(在迭代器中,每个item读完之后,再读下一个,而Stream则将数据分段,每个段都在不同的线程中处理)
Stream的另一个特点是:数据源本身可以是无限的(元素个数不限)。
使用lambdas可以支持许多操作,如 map(汇总mapreduce)、filter(过滤)、limit(限制)、sorted、count、min、max、sum、collect等等。
使用Stream使用懒运算,他们并不会真正的读取所有数据,遇到像getFirst()这样的方法就会结束 链式语法。
接口一:consumer:
consumer接口使用:consumer接口下自带一个方法accept(),用来接收对象传给consumer变量p,然后在后面对其操作。foreach方法需要consumer形参,对consumer中元素遍历
package com.zxc.P; import org.junit.Test; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; /** * Created by Administrator on 2018/2/9 0009. */ public class D { private List<Person> list=new ArrayList<Person>(){ { add(new Person(100,"JACK")); add(new Person(200,"MIKE")); add(new Person(300,"ROSE")); } }; @Test public void test(){ Consumer<Person> consumer=(p)->{System.out.println(p.getName());}; consumer.accept(new Person(200,"MIKE")); } @Test public void test1(){ Consumer<Person> consumer=(p)->{ p.setAge(p.getAge()+10); System.out.println(p.getAge()); }; list.forEach(consumer); } } class Person{ private int age; private String name; public Person() { } public Person(int age, String name) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
接口二、Streams-Predicate接口(断言、断定、判断)
java.util.fuction.Predicate<T>接口定义了一个名叫test的抽象方法,它接收泛型T对象,并返回一个boolean。在需要表示一个涉及类型T的布尔表达式时,就可以使用这个借口。比如:可以定义一个接收String对象的Lambda表达式。
1、过滤器:filter
可以接受一个predicate接口类型的变量,并将所有流对象中的元组进行过滤。该操作是一个中间操作,因此它允许我们在返回结果的基础上再进行其他的流操作(forEach)
以下是一个过滤器filter,用来过滤100到200之间的
package com.zxc.P; import org.junit.Test; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; /** * Created by Administrator on 2018/2/9 0009. */ public class E { private List<Person> list=new ArrayList<Person>(){ { add(new Person(100,"JACK")); add(new Person(200,"MIKE")); add(new Person(300,"ROSE")); } }; @Test public void test(){ //Predicate<Person> predicate=(p)->(p.getAge()>100); //Predicate<Person> predicate1=(p)->(p.getAge()<300); list.stream() .filter((p)->(p.getAge()>100)) .filter((p)->(p.getAge()<300)) .forEach((p)-> System.out.println(p.getAge())); } }
2、test()方法用来测试数据,negate()方法去数据反向
public void test2(){ Predicate<String> predicate=(p)->(p.length()>3); System.out.println(predicate.test("哈尔滨"));//true System.out.println(predicate.negate().test("哈尔滨"));//false Predicate<String> predicate1= Objects::nonNull;//静态方法,判断是否为空无堆 System.out.println("--"+predicate1.test("123")); Predicate<String> predicate2=Objects::isNull;//静态方法,判断是否为空有堆 System.out.println("--"+predicate2.test("456")); Predicate<String> predicate3=String::isEmpty;//静态方法,判断是否为空有堆 System.out.println("--"+predicate3.test("456")); }
3、limit()方法取出限制数量的数据,限制的顺序对过滤出来的信息有影响
public void test4(){ Predicate<String> predicate=(p)->(p.length()>3); list.stream() .limit(2) .forEach((p)-> System.out.println(p.getName())); list.stream() .limit(1) .filter((p)->p.getName().equals("ROSE")) .forEach((p)-> System.out.println(p.getName())); }
4、match方法用来匹配
public void test7(){ System.out.println(StringCollection.stream().anyMatch((p)->p.startsWith("J"))); System.out.println(StringCollection.stream().allMatch((p)->p.startsWith("J"))); System.out.println(StringCollection.stream().noneMatch((p)->p.startsWith("J"))); }
接口三、comparator(比较)
comparator是老java中的经典接口,新的java在此之上添加了多种默认方法。
compare方法用来比较字符串,返回前一个参数首字符减去后一个参数首字符的数字
sorted()方法可以比较两个参数,让其进行比较。
collect()方法可以将结果集收集成一个数组列表。
max() min()方法取最大最小值
public void test(){ Comparator<Person> comparator=(p1,p2)->p1.getName().compareTo(p2.getName()); System.out.println(comparator.compare(new Person(100,"MIKE"),new Person(200,"Rose"))); List<Person> nlist=list.stream() .sorted((p1,p2)->p1.getAge()-p2.getAge()>0?p1.getName().compareTo(p2.getName()):p1.getAge()-p2.getAge()) .limit(3) //.max((p1,p2)->p1.getAge()-p2.getAge()).get.getName(); .collect(Collectors.toList()); //.forEach((p)-> System.out.println(p.getName())); System.out.println(nlist.size()); }
接口四、function流水线接口(Suppliers接口同function一样,但是没有输入参数)
利用Suppliers接口来实例化一个对象
//初始化默认构造器,不可以初始化非默认的 public void test5(){ Supplier<Person> supplier=Person::new; Person p=supplier.get(); p.setName("MIke"); }
apply()方法:应用:类似于Predicate接口下的test()方法,用于放入数据到流水线中
andThen()流水线下一步操作
public void test(){ Function<String,Integer> function=Integer::valueOf; Function<String,String> function1=function.andThen(String::valueOf); System.out.println(function.apply("123")) ; }
map()方法:分类。是一个对于流对象的中间操作,通过给定的方法,它能够把流对象中的每一个元素对应到另外一个对象上。
public void test1(){ List<String> list1=list.stream() .map(Person::getName)//定义就是在聚集的时候执行该对象的定义 .collect(Collectors.toList()); list1.forEach((s)-> System.out.println(s)); System.out.println(list.stream() .map(Person::getName)//定义就是在聚集的时候执行该对象的定义 .collect(Collectors.joining("*"))); }
reduce():汇总、折叠操作。(map将集合类(例如列表)元素进行转换,reduce函数可以将所有值合并成一个,类似于SQL中的sum() count() avg()等聚集函数,接收多个值,返回一个值)
@Test public void test3(){ List<Integer> costBeforeTax = Arrays.asList(100,200,300,400,500); System.out.println(costBeforeTax.stream() .map((a)->a*0.5+a) .reduce((sum,a)->sum+=a) .get()); }
接口五:Optional接口
public void test6(){ Optional empty=Optional.ofNullable(null); System.out.println(empty); Optional<String> s=Optional.ofNullable(null); System.out.println(s.isPresent()); //System.out.println(s.get()); System.out.println(s.orElse("fallback")); }
接口六:ToIntFunction:
方法:summaryStatistic用来计算统计
public void test(){ List<Integer> numbers= Arrays.asList(1,2,3,4,5,6,7,8,9); IntSummaryStatistics is=numbers.stream().mapToInt((x)->x+1).summaryStatistics(); System.out.println(is.getCount()); System.out.println(is.getAverage()); System.out.println(is.getMax()); System.out.println(is.getMin()); System.out.println(is.getSum()); }
五、lambda的环绕式
package com.zxc.P; import org.junit.Test; /** * Created by Administrator on 2018/2/9 0009. */ public class I { @Test public void test(){ System.out.println("start"); System.out.println(ok((p)->p+p+p+p+p+p)); System.out.println("end"); } @FunctionalInterface public interface Iok{ String process(String s); } public String ok(Iok iok){ return iok.process("ok"); } }