函数式接口
函数式接口:有且仅有一个抽象方法的接口
java中的函数式编程体现的就是lambda表达式,所以函数式解救就是可以适用于lambda使用的接口
只有确保接口中有且仅有一个抽象方法,java中的lambda才能顺利的进行推导
-
@FunctionanInterface -
放在接口定义的上方:如果接口是函数式接口,编译通过,如果不是,编译失败
我们自己定义函数式接口的时候@FunctionalInterface是可以选择的,就算我们不写这个注解,只要保证满足函数式接口定义的条件、也照样是函数式接口,但是,建议加上注解
package Demo26;
@FunctionalInterface
public interface InterfaceDemo {
void show();
}
package Demo26;
public class Demo26 {
public static void main(String[] args) {
InterfaceDemo my = () -> System.out.println("函数式接口");
my.show();
}
}
函数式接作为方法的参数
需求
- 定义一个类(RunnableDemo),在类中提供两个方法
一个方法是:startThread(Runnable r) 方法参数Runnable是一个函数式接口
一个方法是主方法,在主方法中调用startThread方法
如果方法的参数是一个函数式接口,我们可以使用lambda表达式作为参数传递
- startThread()->System.out.println(Thread.currentThread().getName()+“线程启动了”);
package Demo27;
public class Demo27 {
public static void main(String[] args) {
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程启动了");
}
});
startThread(()->System.out.println(Thread.currentThread().getName()+"线程启动了"));
}
private static void startThread(Runnable r){
new Thread(r).start();
}
}
函数式接口作为方法的返回值
需求
-
定义一个类(ComparatorDemo),在类中提供两个方法 一个方法是:ComparatorgetComparator() 方法返回值Comparator是一个函数式接口 一个方法是主方法,在主方法中调用getComparator方法 如果方法的返回值是一个函数式接口,我们可以使用lambda表达式作为返回结果
- private static ComparatorgetComparator(){return(s1,s2) -> s1.length()-s2.length()}
package Demo28;
import Demo25.Java_2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
public class ComparatorDemo {
public static void main(String args[]) {
ArrayList<String> array = new ArrayList<String>();
array.add("cccc");
array.add("aa");
array.add("b");
array.add("ddd");
System.out.println("排序前"+array);
Collections.sort(array,getComparator());
System.out.println("排序后"+array);
}
private static Comparator<String> getComparator() {
return (s1,s2) ->{return s1.length()-s2.length();
};
}
}
常用函数式接口—Supplier
Supplier:包含一个无参方法
- T get():获得结果
- 该方法不需要参数,他会安好某种实现逻辑(由lambda表达式实现)返回一个数据
- Supplier接口也被称为生产性接口,如果我们指定了接口是泛型说明类型,那么接口中的get方法就会产生说明类型的数据供我们使用
package Demo1;
import java.util.function.Supplier;
public class Demo26 {
public static void main(String[] args) {
Integer I = getInteger(() -> 30);
System.out.println(I);
String s = getSting(() -> {return "pofen";});
}
private static Integer getInteger(Supplier<Integer> sup){
return sup.get();
}
public static String getSting(Supplier<String> sup){
return sup.get();
}
}
- 练习
- 定义一个类(Demo27)
- 一个方法是:int getMax(supplier sup) 用于返回一个int数组中的最大值
- 一个方法是主方法,在主方法中调用getMax方法
package Demo1;
import java.util.function.Supplier;
public class Demo27 {
public static void main(String[] args) {
int[] arr ={19,26,25,61,48};
int maxValue = getMax(() -> {
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i]>max){
max = arr[i];
}
}
return max;
});
System.out.println(maxValue);
}
private static int getMax(Supplier<Integer> sup){
return sup.get();
}
}
函数式接口—predicate接口
predicate常用的四个方法
- boolean test(T t):对给定的参数进行判断(判断逻辑有lambda表达式实现),返回一个布尔值
- default predicate negate():返回一个逻辑的否定,对应逻辑非
- default predicate and (Predicate other):返回一个组合判断,对应短路与
- default predicate or (predicate other):返回一个组合判断,对应短路或
- predicate接口通常用于判断参数是否满足指定条件
package Demo1;
import java.util.function.Predicate;
public class Demo28 {
public static void main(String[] args) {
boolean b1 = checkString("hello",(String s ) ->{return s.length()>8;});
System.out.println(b1);
boolean b2 = checkString("helloworld",s -> s.length()>8);
System.out.println(b2);
boolean b3 = checkString("hello",s -> s.length()>8,s -> s.length()<15);
System.out.println(b3);
}
private static boolean checkString(String s ,Predicate<String> pre1,Predicate<String> pre2){
return pre1.or(pre2).test(s);
}
private static boolean checkString(String s , Predicate<String> pre){
return pre.negate().test(s);
}
}
Function接口
Function<T,R>:常用的两个方法
- R apply(T t ):将此函数应用于给定的参数
- default Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
- Function<T,R>接口通常用于对参数进行处理,转换(处理逻辑有lambda表达式实现),然后返回一个新的值
package Demo1;
import java.util.function.Function;
public class Demo29 {
public static void main(String[] args) {
convert("100", s -> Integer.parseInt(s));
convert(100, i -> String.valueOf(i + 566));
convert("100",s -> Integer.parseInt(s),i -> String.valueOf(i+566));
}
private static void convert(String s, Function<String, Integer> fun) {
int i = fun.apply(s);
System.out.println(i);
}
private static void convert(int i, Function<Integer, String> fun) {
String s = fun.apply(i);
System.out.println(s);
}
private static void convert(String s ,Function<String,Integer> fun1 ,Function<Integer,String> fun2){
String ss = fun1.andThen(fun2).apply(s);
System.out.println(ss);
}
}
Stream流
需求:
- 创建一个集合,储存多个字符串元素
- 把集合中所有以张开头的元素存储到一个新的集合
- 把张开头的集合中长度为3的元素存储到一个新的集合
- 遍历上一步得到的集合
package Demo1;
import java.util.ArrayList;
public class Demo30 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
ArrayList<String> zhanglist = new ArrayList<>();
for(String s : list){
if(s.startsWith("张")){
zhanglist.add(s);
}
}
ArrayList<String> threelist = new ArrayList<>();
for (String s : zhanglist) {
if (s.length() == 3) {
threelist.add(s);
}
}
for (String s : threelist){
System.out.println(s);
}
System.out.println("-------------------");
list.stream().filter(s -> s.startsWith("张")).filter(s -> s .length()==3).forEach(s -> System.out.println(s));
list.stream().filter(s -> s.startsWith("张")).filter(s -> s .length()==3).forEach(System.out::println);
}
}
使用stream流的方式完成过滤操作
list.stream().filter(s -> s.startsWith("张")).filter(s -> s .length()==3).forEach(System.out::println);
- 直接阅读代码的字面上意思即可完美展示无关逻辑方式的语义:生成流,过滤姓张,过滤长度为3,逐一打印
Stream流的生成方式
Stream流的使用
通过数据源(集合,数组等)生成流
list.stream()
一个流后面可以跟随0个或者多个中间操作,其目的主要是打开流,作出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用
filter()
一个流只能有一个终结操作,当这个操作执行后,流就被使用“光”了,无法再被操作,所以这必定是流的最后一个操作
foreach()
Sream常见的生成方式
- Collection体现的集合可以使用默认方法stream()生成流
default Stream stream()
- Map体系的集合间接生成流
- 数组可以通过Stream接口静态方法of(T…values)生成流
package Demo1;
import java.util.*;
import java.util.stream.Stream;
public class Demo31 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Stream<String> listStrema = list.stream();
Set<String> set = new HashSet<>();
Stream<String> setStream = set.stream();
Map<String,Integer> map = new HashMap<>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String,Integer>> entryStream = map.entrySet().stream();
String[] strArray = {"hello","word","java"};
Stream<String> strArrayStream = Stream.of(strArray);
Stream<String> strArraySAtream2 = Stream.of("hello","woeld","java");
Stream<Integer> intStream = Stream.of(10,20,30);
}
}
|