java的函数式接口多数位于package java.util.function;包下
function代表了一个函数,接收一个参数返回一个结果。function内部有一个apply方法,两个default方法,还有一个static方法。
function包含两个泛型:
* @param the type of the input to the function
* @param the type of the result of the function
package five;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Test3 {
public static void main(String[] args) {
// ()表示该函数式接口的方法,不接受参数,不返回结果
// 对于“()->{}”的表达式,必须通过上下文来判断。
// ()里的表示方法的 参数,{}表示是是方法的实现。编译器会去找目标函数接口的方法。
TheInterface i1 = () -> {
};
System.out.println(i1.getClass().getInterfaces()[0]);
TheInterface i2 = () -> {
};
System.out.println(i2.getClass().getInterfaces()[0]);
/**
* runnable的函数式接口 因为runnable接口唯一的抽象方法run不接受参数,不返回值 因此可以使用lambda表达式的形式去调用
*/
new Thread(() -> {
System.out.println("aaaa");
}).start();
/**
* 将list中的字母转换大小写输出,使用lambda
*/
List list = Arrays.asList("abc", "bcv");
// consumer是函数式接口之一,功能就是接受参数,不返回值
list.forEach(item -> System.out.println(item.toUpperCase()));
// 将元素放到list2中
List list2 = new ArrayList<>();
list.forEach(item -> list2.add(item.toUpperCase()));
list2.forEach(item -> System.out.println(item));
// 换一种写法,使用stream的方式编写,stream是个串行流,操作由一个线程完成。
/**
* default 表示是个默认的接口方法,方法返回一个串行流,与linux的管道类似。
* 与之相对的是并行流parallelStream,区别就在于是否多线程。 流还分中间流,返回一个流;结点流:不再返回流,已经到达最终结果
* default Stream stream() { return
* StreamSupport.stream(spliterator(), false); }
*/
// map接收两个参数,前面表示输入,后面表示输出,map仍然返回一个stream
list.stream().map(item -> item.toUpperCase()).forEach(item -> System.out.println(item));
//使用方法引用的方式实现,String::toUpperCase编译器根据参数类型和返回结果推断。
//方法引用可以通过类,对象,构造方法去引用。
//调用方法的对象作为该函数的输入,输出就是return出来的输出
list.stream().map(String::toUpperCase).forEach(item -> System.out.println(item));
//对于类名::方法引用的形式,那么他所对应的lambda表达式第一个参数类型就是调用该方法的对象
//也就是Function的第一个参数就是调用后面方法的那个对象
Function function = String::toUpperCase;
System.out.println(function.getClass().getInterfaces()[0]);
}
}
@FunctionalInterface
interface TheInterface {
void myMethod();
}
@FunctionalInterface
interface TheInterface2 {
void myMethod2();
}
package six;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class StringComparetor {
public static void main(String[] args) {
List names = Arrays.asList("zhangsan", "lisi", "wangwu");
Collections.sort(names, new Comparator() {
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
return o2.compareTo(o1);
}
});
System.out.println(names);
Collections.sort(names, (String o1, String o2) -> {
return o2.compareTo(o1);
});
// reverseOrder是1.8新增的方法
Collections.sort(names, Comparator.reverseOrder());
// 由于names是String类型,所以编译器可以自动推导出函数输入类型和输出类型
// 因此可以省略掉函数式方法调用(String o1, String o2)中的类型声明String
Collections.sort(names, (o1, o2) -> {
return o2.compareTo(o1);
});
// 还可以用另一种写法,去掉{}
Collections.sort(names, (o1, o2) -> o2.compareTo(o1));
System.out.println(names);
}
}
lambda表达式的作用:传递行为,不仅是传递值,提升抽象层次,api重用性更好,更加灵活。
lambda的原始形式是:(type1 arg1,type2 arg2) -> {body}
如果参数可以推断,那么可以写成(arg1,arg2) -> {body}
如果参数只有一个,并且类型是可以推导出来,那么()可以省略arg1 -> {body}
如果函数主体只有一条语句,那么{}可以省略arg1 -> body;如果函数主体不止一条语句,那么{}不可省略。
例如:(o1, o2) -> o2.compareTo(o1)这句话,还可以省略掉return语句。o2.compareTo(o1)称为表达式expression,如果变成return o2.compareTo(o1),那么必须使用{}围起来,这种被称为statement。
package six;
import java.util.function.Function;
public class FunctionTest {
public static void main(String[] args) {
FunctionTest test = new FunctionTest();
// 注意return 2 * value;必须写分号
// 调用的时候,将1传给a,执行apply的时候实际上执行的就是{return 2 * value;},这就是传递行为
// statement的形式
System.out.println(test.compute(1, value -> {
return 2 * value;
}));
// 表达式形式
System.out.println(test.compute(2, value -> 5 + value));
// 返回值与输入值不同类型
System.out.println(test.convert(5, value -> String.valueOf(value + " hello!")));
//也可以先定义好Function,然后直接调用该函数
Function function = value -> value * 2;
System.out.println(test.compute(2, function));
}
public int compute(int a, Function function) {
// 此处的apply是使用者在使用的时候传递的,称为传递行为
int result = function.apply(a);
return result;
}
public String convert(int a, Function function) {
return function.apply(a);
}
}
与传统不同的是:以前需要将行为定义好,而现在不需要定义行为,行为在执行调用的时候传入。 高阶函数:如果一个函数接收一个函数作为参数或者返回一个函数作为返回值,那么这个函数的函数叫高阶函数。