JDK8中部分函数式操作的实现讲解(一)

在JDK8中添加了java.util.function包,该包中是用于一些函数式接口,这些接口被用于改造JDK原有的一些接口添加Lambda调用方式的函数式方法。

List等实现了Iterable接口的类:

package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
/**
 * 拿客
 * www.coderknock.com
 * QQ群:213732117
 * 创建时间:2016年07月23日
 * 描述:
 */
public interface Iterable<T> {
 
    Iterator<T> iterator();

    /**
     * 迭代的每个元素并执行特定动作的代码直到所有的元素都被处理或抛出异常。
     * 除非实现类的其他的实现, 否则,
     * action中的操作是在迭代的顺序中执行的(如果迭代顺序指定)。  
     * 异常会传递给action的调用对象。
     *
     * @implSpec
     * <p>The default implementation behaves as if:
     * <pre>{@code
     *     for (T t : this)
     *         action.accept(t);
     * }</pre>
     *
     * @param action 为每个元素执行的操作
     * @throws NullPointerException 如果指定的操作是空的
     * @since 1.8
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

   
    default Spliterator<T> spliterator() {
      	//根据迭代器创建一个分片迭代器
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

我们来看下Consumer:

package java.util.function;

import java.util.Objects;
/**
 * 拿客
 * www.coderknock.com
 * QQ群:213732117
 * 创建时间:2016年07月23日
 * 描述:
 */
/**
 * 表示接受一个输入参数,并返回没有结果的操作。不像大多数其他的功能接口,Consumer is expected
 * to operate via side-effects.预计通过副作用。
 *
 * 这是一个函数接口,函数方法为accept(T t) 
 *
 * @param <T> 输入到操作的类型
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    /**
     * 在给定的参数上执行此操作。
     *
     * @param t 输入的参数
     */
    void accept(T t);

    /**
     * 返回一个Consumer对象,其在执行accept之后执行传入的after中的accept,从而可以执行多重操作
     *
     * @param after 此操作后执行的操作
     * @return 返回一个Consumer对象,其操作为自身的accept以及after中的accept
     * @throws NullPointerException
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

通过forEach的示例来看一下是怎么实现的:

List<String> list = new ArrayList<>();
/**
下面代码时非Lambda的forEach写法
list.forEach(new Consumer<String>() {
            @Override
            public void accept(String x) {
                System.out.println(x);
            }
        });
**/
list.forEach(x -> System.out.println(x));

上面语句中x -> System.out.println(x)实际上是创建了一个Consumer,该Consumer的泛型在编译器编译时会根据List的泛型进行判断,如果没有声明则默认Object。

Stream的Filter

Stream的filter方法如下:

Stream<T> filter(Predicate<? super T> predicate);

Predicate其实就是提供了一个boolean类型的返回值方法的函数接口,其源码如下:

package java.util.function;

import java.util.Objects;
/**
 * 拿客
 * www.coderknock.com
 * QQ群:213732117
 * 创建时间:2016年07月23日
 * 描述:
 */
/**
 * 表示对一个参数的断言的结果(布尔值函数)。
 *
 * 这是一个函数接口,函数方法是test(Object)
 *
 * @param <T> 输入到断言的类型
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Predicate<T> {

    /**
     * 在给定的参数上计算这个断言。
     *
     * @param t 输入的参数
     * @return 如果参数匹配断言返回true,否则返回false
     */
    boolean test(T t);

 
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
	
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
	
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

还是使用上面的list变量,其stream写法如下:

/**
//非lambda写法
list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String x) {
                return x.equals("test");
            }
        });
**/
list.stream().filter(x -> x.equals("test"));

上面语句中x -> x.equals("test")实际上是创建了一个Predicate,该Predicate的泛型在编译器编译时会根据List的泛型进行判断,如果没有声明则默认Object。

如果你写成list.stream().filter(x -> x==1);是会编译错误的,编译时编译器通过类型推断可以确定x是String类型,所以使用x==1时会报错:

D:\Work\LearnJavaFX\src>javac -encoding utf-8 LambdaTest.java
LambdaTest.java:20: 错误: 不可比较的类型: String和int
                return x==1;
                        ^
1 个错误

转载于:https://my.oschina.net/coderknock/blog/716636

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值