使用者角度看Java8函数式编程

前言:作者本人无函数式编程经验,看了函数式编程后,有些粗浅的认识,记录下,避免遗忘。

1 函数式编程解决了什么问题?

函数式编程解决了,java中丑陋的内部类代码。很多人提到函数式编程,都是list.foreach举例,我要用大家熟悉的runnable举例,“hello word”走起,异步打印最简单的例子

a 常规写法
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("hello world");
			}
		});
		
		t.start();
		t.join();
	}
b lambda 函数式编程写法
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(()->System.out.println("hello world"));
		
		t.start();
		t.join();
	}

可以看到,函数写法,短短3行代码,解决问题。

c lambda 写法2
	public static void main(String[] args) throws InterruptedException {
		Runnable run = ()->System.out.println("hello world");
		Thread t = new Thread(run);
		t.start();
		t.join();
	}
这样应该更好理解,()->System.out.println("hello world")就是接口(Runnable)的一个实现。

d Thread有多个构造函数,函数式编程时,编译器怎么知道是哪个?元芳,怎么看


元芳:大人,此事必有蹊跷。连Eclipse都能分析到,编译器肯定可以搞定。

首先,Thread的构造函数中,接受一个形式参数的,就一个,所以构造函数肯定是Thread(Runnable target),其次如果有2个构造函数,这2个构造函数都接受一个形式参数,如果只有Runnable是函数式接口,编译器也找得到,不会报错。这里要说说函数式接口。

2 函数式接口


Runnable上面增加了一个注解,表明Runnable是一个函数式接口。Java 库中的所有相关接口都已经带有这个注解了。

就像正方形也是矩形一样,函数式接口,也是一个接口(interface),要求接口里面只有一个方法,是个特殊的接口,就如正方形是特殊的矩形。而Runnable接口里面只有一个Run方法,满足函数式接口的要求,自然是一个函数式接口了。

到这里就不难理解,编译器是如何工作的了,因为函数式接口,只有一个方法,那么()->System.out.println("hello world")就是实现了这唯一的一个方法了。函数式编程原来如此简单。

由于Runnable.run()没有形式参数,所以函数式编程()->System.out.println("hello world")也是没有形式参数的。

3 补充

举个接受一个参数的例子

Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );

forEach是Collection集合类新增的方法,看看ArrayList的forEach实现

    @Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

写了很多,大部分都是防止在遍历的时候,修改list,防止多线程出错,我把多线程去掉,代码如下

    public void forEach(Consumer<? super E> action) {
        final int size = this.size;
        for (int i=0; i < size; i++) {
            action.accept(elementData[i]);
        }
    }

不用多说了,这个简单吧,forEach完全可以用传统的内部类实现,我要复辟下。

		Consumer<Integer> action = new Consumer<Integer>() {
			
			@Override
			public void accept(Integer t) {
				System.out.println(t);
			}
		};
		
		list.forEach(action);

还有很多要补充的,例如:凡事都有例外,前面说了函数式接口,是只有一个方法的接口,但可以有静态方法和默认方法。静态方法和默认方法请参考http://blog.csdn.net/u014470581/article/details/54944384


这篇文章写得很深刻

http://blog.csdn.net/hnulwt/article/details/44338637

这篇文章写得很全面

http://blog.csdn.net/u014470581/article/details/54944384




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值