import java.util.Comparator; import java.util.function.Consumer; public class LambdaTest { public static void main(String[] args) { //语法格式一:无参,无返回值 Runnable r1 = () -> { System.out.println("我爱中华!"); }; r1.run(); //语法格式二:Lambda需要一个参数,但是没有返回值 Consumer<String> consumer1 = (String str) -> { System.out.println(str); }; consumer1.accept("谎言和誓言的区别是什么呢?"); //语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断” Consumer<String> consumer2 = (str) -> System.out.println(str); consumer2.accept("一个是听的人当真了,一个是说的人当真了。"); //语法格式四:Lambda若只需要一个参数,参数的小括号可以省略 Consumer<String> consumer3 = str -> System.out.println(str); consumer3.accept("花开花落几时回?"); //语法格式五:Lambda需要两个或以上的参数,多条执行语句,并且可以有返回值 Comparator<Integer> comparator1 = (o1,o2) -> { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); }; System.out.println(comparator1.compare(12, 21)); //语法格式六:当Lambda体只有一条执行语句时,return 与大括号若有,都可以省略 Comparator<Integer> comparator2 = (o1,o2) -> o1.compareTo(o2); System.out.println(comparator2.compare(12, 6)); } }
如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。可以通过Lambda表达式来创建该接口的对象。若Lambda表达式抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽象方法上进行声明。可以通过在一个接口上使用@FunctionalInterface注解,这样可以检查它是否是一个函数时接口。同时javadoc也会包含一条声明,说明这个接口是一个函数式接口。匿名实现类表示都可以用Lambda表达式来写。
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer<T>消费型接口 | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
Supplier<T> 供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get() |
Function<T,R> 函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t) |
Predicate<T> 断定型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t) |
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; public class FunctionalInterface { public static void main(String[] args) { FunctionalInterface test = new FunctionalInterface(); List<String> list = Arrays.asList("北京","天津","南京","西京","东京","开封"); test.happyTime(400,money -> System.out.println("今天共消费" + money)); List<String> string = test.filterString(list,str -> str.contains("京")); System.out.println(string); } public void happyTime(double money,Consumer<Double> consumer){ consumer.accept(money); } //根据给定的规则,过滤集合中的字符串。此规则由Predicate的方法决定 public List<String> filterString(List<String> list,Predicate<String> predicate){ ArrayList<String> filterList = new ArrayList<>(); for (String str : list) { if(predicate.test(str)){ filterList.add(str); } } return filterList; } }
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
BiFunction<T,U,R> | T,U | R | 对类型为T,U参数应用操作,返回R类型的结果。,包含方法:R apply(T t,U u) |
UnaryOperator<T>(Function子接口) | T | T | 对类型为T的对象进行一元运算,并返回T类型的结果。包含方法为:T apply(T t) |
BinaryOperator<T>(BiFunction子接口) | T,T | T | 对类型为T的对象进行二元运算,并返回T类型的结果。包含方法:T apply(T t1,T t2) |
BiConsumer<T,U> | T,U | void | 对类型为T,U参数应用操作。包含方法为:void accept(T t,U u) |
BiPredicate<T,U> | T,U | boolean | 包含方法:boolean test(T t,U u) |
ToIntFunction<T> | T | int | 计算int值的函数 |
ToLongFunction<T> | T | long | 计算long值的函数 |
ToDoubleFunction<T> | T | double | 计算double值的函数 |
IntFunction<R> | int | R | 参数为int类型的函数 |
LongFunction<R> | long | R | 参数为long类型的函数 |
DoubleFunction<R> | double | R | 参数为double类型的函数 |
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用。方法引用可以看做是Lambda表达式的深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法。方法引用要求实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!(针对情况一和情况二)格式:使用操作符“::”将类(或对象)与方法名分隔开来。
如下三种主要使用情况
import java.io.PrintStream; import java.util.Comparator; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; public class MethodReference { public static void main(String[] args) { //情况一:对象::实例方法 //Consumer中的 void accept(T t) //PrintStream中的 void println(T t) PrintStream printStream = System.out; Consumer<String> consumer = printStream::println; consumer.accept("Sakura"); //情况二:类::静态方法 //Supplier中的 T get() //Person中的 String gerName() Person person = new Person("Sakura",10); Supplier supplier = person::getAge; System.out.println(supplier.get()); //情况三:类::非静态方法 //Comparator中的 int compare(T t1,T t2) //Integer中的 int compare(T t1,T t2) Comparator<Integer> comparator = Integer::compare; System.out.println(comparator.compare(10, 13)); System.out.println(); //Function中的 R apply(T t) //Math中的 Long round(Double d) Function<Double,Long> fun1 = new Function<Double,Long>() { @Override public Long apply(Double d) { return Math.round(d); } }; System.out.println(fun1.apply(12.3)); Function<Double,Long> fun2 = d -> Math.round(d); System.out.println(fun2.apply(21.5)); Function<Double,Long> fun3 = Math::round; System.out.println(fun3.apply(33.7)); System.out.println(); //Comparator中的 int comapre(T t1,T t2) //String中的 int t1.comparaTo(t2) Comparator<String> comparator2 = String::compareTo; System.out.println(comparator2.compare("intel", "amd")); //Function中的 R apply(T t) //Person中的 String getName() Function<Person,String> fun4 = Person::getName; System.out.println(fun4.apply(person)); } }
public class Person { private String name; private int age; public Person() { } public Person(String name) { this.name = name; } public Person(String name, int age) { this(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 String toString(){ return "Person{ name:" + name + ",age:" + age + "}"; } }
构造器引用与方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致。抽象方法的返回值类型即为构造器所属的类的类型。
import java.util.function.Function; import java.util.function.Supplier; public class ConstructorReference { public static void main(String[] args) { //Supplier中的 T get() Supplier<Person> supplier = Person::new; System.out.println(supplier.get()); //Function中的 R apply(T t) Function<String,Person> fun = Person::new; System.out.println(fun.apply("Sakura")); //BiFunction中 R apply(T t,U u) BiFunction<String,Integer,Person> biFunction = Person::new; System.out.println(biFunction.apply("Sakura", 9)); } }
public class Person { private String name; private int age; public Person() { } public Person(String name) { this.name = name; } public Person(String name, int age) { this(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 String toString(){ return "Person{ name:" + name + ",age:" + age + "}"; } }
可以把数组看做是一个特殊的类,则写法与构造器引用一致;
import java.util.Arrays; import java.util.function.Function; public class ArrayReferences { public static void main(String[] args) { Function<Integer,String[]> fun1 = length -> new String[length]; String[] array1 = fun1.apply(5); System.out.println(Arrays.toString(array1)); Function<Integer,String[]> fun2 = String[]::new; String[] array2 = fun2.apply(10); System.out.println(Arrays.toString(array2)); } }
Stream API(java.util.stream)把真正的函数式接口编程风格引入到Java中。Stream是Java 8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简言之,Stream API提供了一种高效且易于使用的处理数据的方式。
创建Stream的操作三个对象
import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class StreamTest { public static void main(String[] args) { //创建Stream方式一:通过集合 List<Integer> list = Arrays.asList(1,2,3,4,5); //default Stream<E> stream():返回一个顺序流 Stream<Integer> stream = list.stream(); //default Stream<E> parallelStream():返回一个并行流 Stream<Integer> parallelStream = list.parallelStream(); //创建Stream方式二:通过数组 Object[] object = list.toArray(); //调用Arrays类的static <T> Stream<T> stream(T[] array):返回一个流 Stream<Object> stream1 = Arrays.stream(object); //创建Stream方式三:通过Stream的of() Stream<Integer> stream2 = Stream.of(1,2,3,4,5); //创建Stream方式四:创建无限流 //public static<T> Stream<T> iterate(final T seed,final UnaryOperator<T> f) //迭代 Stream.iterate(0, t->t+2).limit(10).forEach(System.out::println); //public static<T> Stream<T> generate(Supplier<T> s) //生成 Stream.generate(Math::random).limit(10).forEach(System.out::println); } }
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次从全部处理,称为“惰性求值”。
筛选与切片
Stream<T> filter(Predicate<? super T> predicate) //接收Lambda,从流中排除某些元素 Stream<T> distinct() //筛选,通过流所生成元素的hashCode()和equals()去除重复元素 Stream<T> limit(long maxSize) //截断流,使其元素不超过给定数量 Stream<T> skip(long n) //跳过元素,返回一个扔掉前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(long maxSize)互补
import java.util.ArrayList; import java.util.List; public class StreamTest { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person("Sakura",9)); list.add(new Person("Akame",17)); list.add(new Person("Miloto",13)); list.add(new Person("Shana",15)); list.add(new Person("Nanoha",11)); //filter(Predicate<? super T> predicate) //接收Lambda,从流中排除某些元素 list.stream().filter(person -> person.getAge()<=13).forEach(System.out::println); System.out.println(); //limit(long maxSize) //截断流,使其元素不超过给定数量 list.stream().limit(3).forEach(System.out::println); System.out.println(); //skip(long n) //跳过元素,返回一个扔掉前n个元素的流。若流中元素不足n个,则返回一个空流。 list.stream().skip(3).forEach(System.out::println); System.out.println(); //distinct() //筛选,通过流所生成元素的hashCode()和equals()去除重复元素 list.add(new Person("Rimuru",10)); list.add(new Person("Rimuru",10)); list.add(new Person("Rimuru",11)); list.add(new Person("Rimuru",11)); list.add(new Person("Rimuru",11)); list.stream().distinct().forEach(System.out::println); } }
public class Person { private String name; private int age; public Person() { } public Person(String name) { this.name = name; } public Person(String name, int age) { this(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 String toString(){ return "Person{ name:" + name + ",age:" + age + "}"; } public boolean equals(Object obj) { if(obj instanceof Person){ Person person = (Person)obj; if(name.equals(person.name)){ if(age == person.age){ return true; } } } return false; } public int hashCode() { return name.hashCode()+age; } }
映射
<R> Stream<R> map(Function<? super T,? extends R> mapper) //接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素 DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) //接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStream IntStream mapToInt(ToIntFunction<? super T> mapper) //接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntStream LongStream mapToLong(ToLongFunction<? super T> mapper) //接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的LongStream <R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper) //接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有的流连接成一个流
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class StreamTest { public static void main(String[] args) { List<String> list = Arrays.asList("aa","bb","cc","dd"); Stream<Stream<Character>> streamStrean = list.stream().map(StreamTest::fromStringToStream); streamStrean.forEach(s -> s.forEach(System.out::println)); System.out.println(); Stream<Character> characterStream = list.stream().flatMap(StreamTest::fromStringToStream); characterStream.forEach(System.out::println); } //将字符串中的多个字符构成的集合转换为对应的Stream的实例 public static Stream<Character> fromStringToStream(String str){ ArrayList<Character> list = new ArrayList<>(); for (Character character : str.toCharArray()) { list.add(character); } return list.stream(); } }
排序
Stream<T> sorted() //产生一个新流,其中按自然顺序排序 Stream<T> sorted(Comparator<? super T> comparator) //产生一个新流,其中按比较器顺序排序
import java.util.ArrayList; import java.util.List; public class StreamTest { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person("Sakura",9)); list.add(new Person("Akame",17)); list.add(new Person("Miloto",13)); list.add(new Person("Shana",15)); list.add(new Person("Nanoha",11)); list.stream().sorted().forEach(System.out::println); System.out.println(); list.stream().sorted((e1,e2) -> Integer.compare(e1.getAge(),e2.getAge())).forEach(System.out::println); } }
public class Person implements Comparable{ private String name; private int age; public Person() { } public Person(String name) { this.name = name; } public Person(String name, int age) { this(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 String toString(){ return "Person{ name:" + name + ",age:" + age + "}"; } @Override public int compareTo(Object o) { if(o instanceof Person){ Person person = (Person)o; int compare = this.name .compareTo(person.name); if(compare != 0){ return compare; } else { return Integer.compare(this.age, person.age); } } throw new RuntimeException("传入的数据类型不一致!"); } }
终止操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是void。流进行终止操作后,不能再次使用。
匹配与查找
boolean allMatch(Predicate<? super T> predicate) //检查是否匹配所有元素 boolean anyMatch(Predicate<? super T> predicate) //检查是否至少匹配一个元素 boolean noneMatch(Predicate<? super T> predicate) //检查是否没有匹配所有元素 Optional<T> findFirst() //返回第一个元素 Optional<T> findAny() //返回当前流中的任意元素 long count() //返回流中元素总数 Optional<T> max(Comparator<? super T> comparator) //返回流中最大值 Optional<T> min(Comparator<? super T> comparator) //返回流中最小值 void forEach(Consumer<? super T> action) //内部迭代
import java.util.Arrays; import java.util.List; import java.util.Optional; public class StreamTest { public static void main(String[] args) { List<Integer> list = Arrays.asList(7,17,10,9,11,13,15); boolean allMath = list.stream().allMatch(e -> e<13); System.out.println(allMath); boolean anyMath = list.stream().anyMatch(e -> e<=10); System.out.println(anyMath); boolean noneMath = list.stream().noneMatch(e -> e==7); System.out.println(noneMath); Optional<Integer> first = list.stream().findFirst(); System.out.println(first); Optional<Integer> any = list.parallelStream().findAny(); System.out.println(any); long count = list.stream().count(); System.out.println(count); Optional<Integer> max = list.stream().max(Integer::compare); System.out.println(max); Optional<Integer> min = list.stream().min((e1,e2) -> Integer.compare(e1, e2)); System.out.println(min); list.stream().forEach(System.out::println); } }
规约
Optional<T> reduce(BinaryOperator<T> accumulator) //可以将流中元素反复结合起来,得到一个值,返回Optional<T> T reduce(T identity, BinaryOperator<T> accumulator) //可以将流中元素反复结合起来,得到一个值,返回T
import java.util.Arrays; import java.util.List; import java.util.Optional; public class StreamTest { public static void main(String[] args) { List<Integer> number = Arrays.asList(1,2,3,4,5,6,7,8,9,10); int sum = number.stream().reduce(10,Integer::sum); System.out.println(sum); Optional<Integer> sum1= number.stream().reduce(Integer::sum); System.out.println(sum1); } }
收集
<R,A> R collect(Collector<? super T,A,R> collector) //将流转换成其它形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
public class StreamTest { public static void main(String[] args) { List<Integer> list1 = Arrays.asList(7,17,10,9,11,13,15); list1.stream().filter(e -> e<=13).collect(Collectors.toList()).forEach(System.out::println); System.out.println(); list1.stream().filter(e -> e<=10).collect(Collectors.toList()).forEach(System.out::println); } }
Optional
public static <T> Optional<T> of(T value) //创建一个Optional实例,t必须非空 public static <T> Optional<T> empty() //创建一个空的Optional实例 public static <T> Optional<T> ofNullable(T value) //t可以为null public boolean isPresent() //判断是否包含对象 public void ifPresent(Consumer<? super T> action) //如果有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它 public T get() //如果调用对象包含值,返回该值,否则抛异常 public T orElse(T other) //如果有值则将其返回,否则返回指定的other对象 public T orElseGet(Supplier<? extends T> supplier) //如果有值则将其返回,否则返回由Supplier接口实现提供的对象 public T orElseThrow() //如果有值则将其返回,否则抛出由Supplier接口实现提供的异常
public class OptionalTest { public static void main(String[] args) { Boy boy = new Boy(); String grilName = Boy.getGrilName(boy); System.out.println(grilName); boy = null; grilName = Boy.getGrilName(boy); System.out.println(grilName); boy = new Boy("Akame", 13, new Gril("Mikoto Misaka", 13)); grilName = Boy.getGrilName(boy); System.out.println(grilName); } }
public class Person{ private String name; private int age; public Person() { } public Person(String name) { this.name = name; } public Person(String name, int age) { this(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 String toString(){ return "Person{ name:" + name + ",age:" + age + "}"; } }
import java.util.Optional; public class Gril extends Person{ private Boy boy; public Gril(){ } public Gril(String name){ super(name); } public Gril(String name,int age){ super(name, age); } public Gril(String name,int age,Boy boy){ super(name, age); this.boy = boy; } public void setBoy(Boy boy){ this.boy = boy; } public Boy getBoy(){ return boy; } public String toString(){ return "Person{ name:" + getName() + ",age:" + getAge() + "boy:" + boy + "}"; } public static String getBoyName(Gril gril){ Optional<Gril> grilOptional = Optional.ofNullable(gril); //此时gril1一定非空 Gril gril1 = grilOptional.orElse(new Gril("Sakura",9,new Boy("Kikyou",9))); Boy boy = gril1.getBoy(); Optional<Boy> griloOptional = Optional.ofNullable(boy); //此时boy1一定非空 Boy boy1 = griloOptional.orElse(new Boy("Kagome",9)); return boy1.getName(); } }
import java.util.Optional; public class Boy extends Person{ private Gril gril; public Boy(){ } public Boy(String name){ super(name); } public Boy(String name,int age){ super(name, age); } public Boy(String name,int age,Gril gril){ super(name, age); this.gril = gril; } public void setGril(Gril gril){ this.gril = gril; } public Gril getGril(){ return gril; } public String toString(){ return "Person{ name:" + getName() + ",age:" + getAge() + "gril:" + gril + "}"; } public static String getGrilName(Boy boy){ Optional<Boy> boyOptional = Optional.ofNullable(boy); //此时boy1一定非空 Boy boy1 = boyOptional.orElse(new Boy("Rimuru",10,new Gril("Mikoto",10))); Gril gril = boy1.getGril(); Optional<Gril> griloOptional = Optional.ofNullable(gril); //此时gril1一定非空 Gril gril1 = griloOptional.orElse(new Gril("Misaka",10)); return gril1.getName(); } }