Jdk8之后新增的一个重要的包 : java.util.function
该包下所有的接口都是函数式接口, 按分类主要分为四大接口类型: Function、Consumer、Predicate、Supplier
| 接口 | 参数 | 返回值 | 说明 |
| Supplier | 无 | T | 供给型:无参,返回一个执行泛型对象 |
| Consumer | T | 无参 | 消费型:传入一个指定参数,无返回值 |
| Function | T.R | R | 方法型:输入一个参数得到一个结果 |
可以看下Java在function包下的代码:
Consumer
源码如下(包含一个接口和默认实现)
@FunctionalInterface public interface Consumer{ void accept(T t); default Consumer andThen(Consumer super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
使用案例
public static void main(String[] args) {
testConsumer();
testAndThen();
}
public static void testConsumer() {
//设置好Consumer实现方法
Consumer square = x -> System.out.println("平方计算 : " + x * x);
//传入值
square.accept(2);
}
public static void testAndThen() {
//当前值
Consumer consumer1 = x -> System.out.println("当前值 : " + x);
//相加
Consumer consumer2 = x -> { System.out.println("相加 : " + (x + x)); };
//相乘
Consumer consumer3 = x -> System.out.println("相乘 : " + x * x);
//andThen拼接
consumer1.andThen(consumer2).andThen(consumer3).accept(1);
}
这个是一个没有使用意义的DEMO,其实我们在使用consumer的时候,一般会用来操作集合,JDK的iterator接口就是使用consumer来操作的
另一种使用案例
public static void main(String[] args) {
//假设这里有个集合,集合里的对象有个status属性,现在我想对这个属性赋值一个固定值
List pensionList = new ArrayList<>();
//1、传统的通过for循环添加
for (Pension pension : pensionList) {
pension.setStatus(1);
}
//2、通过forEach的Consumer添加
pensionList.forEach(x -> x.setStatus(1));
}
这样一比较是不是代码简洁了点,这就是Consumer是我们代码带来简洁的地方。
Supplier
提前定义可能返回的一个指定类型结果,等需要调用的时候再获取结果
我们看下源码
publicT orElseThrow(Supplier extends X> exceptionSupplier) throws X { if (value != null) { return value; } else { throw exceptionSupplier.get(); } }
使用案例
public static void main(String[] args) {
Person son = null;
//先判断son是否为null,如果为不为null则返回当前对象,如果为null则返回新创建的对象
BrandDTO optional = Optional.ofNullable(son).orElseGet(() -> new Person());
}
Function
实现一个”一元函数“,即传入一个值经过函数的计算返回另一个值
源码
@FunctionalInterface
public interface Function {
R apply(T t);
default java.util.function.Function compose(java.util.function.Function super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default java.util.function.Function andThen(java.util.function.Function super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static java.util.function.Function identity() {
return t -> t;
}
}
使用案例
public static void main(String[] args) {
applyTest();
andThenTest();
composeTest();
test();
}
private static void applyTest() {
//示例1:定义一个funciton,实现将String转换为Integer
Function function = x -> Integer.parseInt(x);
Integer a = function.apply("100");
System.out.println(a.getClass());
// 结果:class java.lang.Integer
}
private static void andThenTest() {
//示例2:使用andThen() 实现一个函数 y=10x + 10;
//先执行 10 * x
Function function2 = x -> 10 * x;
//通过andThen在执行 这里的x就等于上面的10 * x的值
function2 = function2.andThen(x -> x + 10);
System.out.println(function2.apply(2));
//结果:30
}
private static void composeTest() {
//示例3:使用compose() 实现一个函数 y=(10+x)2;
Function function3 = x -> x * 2;
//先执行 x+10 在执行(x+10)*2顺序与上面相反
function3 = function3.compose(x -> x + 10);
System.out.println(function3.apply(3));
//结果:26
}
private static void test() {
//示例4:使用使用compose()、andThen()实现一个函数 y=(10+x)*2+10;
//执行第二步
Function function4 = x -> x * 2;
//执行第一步
function4 = function4.compose(x -> x + 10);
//执行第三步
function4 = function4.andThen(x -> x + 10);
System.out.println(function4.apply(3));
//结果:36
}
在JDK中内部的使用案例
Map> map = new HashMap<>(); List list; // java8之前写法 list = map.get("key"); if (list == null) { list = new linkedList<>(); map.put("key", list); } list.add("11"); // 使用 computeIfAbsent 可以这样写 如果key返回部位空则返回该集合 ,为空则创建集合后返回 list = map.computeIfAbsent("key", k -> new ArrayList<>()); list.add("11");
public static void main(String[] args) {
List persionList = new ArrayList();
persionList.add(new Person(1,"张三","男",38));
persionList.add(new Person(2,"小小","女",2));
persionList.add(new Person(3,"李四","男",65));
//1、只取出该集合中所有姓名组成一个新集合(将Person对象转为String对象)
List nameList=persionList.stream().map(Person::getName).collect(Collectors.toList());
System.out.println(nameList.toString());
}
一般我们也会很少去定义一个方法,方法参数包含函数接口。我们更重要的是学会使用JDk8中带有函数式接口参数的方法,来简化我们的代码



