JDK1.8中的Lambda公式--02【Optional】

1.使用只有一个方法的接口来表示某特定方法并反复使用, 是很早就有的习惯。 使用 Swing编写过用户界面的人对这种方式都不陌生, 例 2-2 中的用法也是如此。 这里无需再标新立异, Lambda 表达式也使用同样的技巧, 并将这种接口称为函数接口。 
表2-1 Java中重要的函数接口
    接口                         参数         返回类型                     示例
    Predicate<T>            T             boolean                   这张唱片已经发行了吗
    Consumer<T>           T             void                         输出一个值
    Function<T,R>           T             R                             获得 Artist 对象的名字
    Supplier<T>            None         T                             工厂方法
    UnaryOperator<T>     T             T                            逻辑非( !)

 

    BinaryOperator<T>     (T, T)       T                          求两个数的乘积( *)

 

2.@FunctionalInterface 注释

 该注释会强制 javac 检查一个接口是否符合函数接口的标准。 如果该注释添加给一个枚举类型、 类或另一个注释, 或者接口包含不止一个抽象方法, javac 就会报错。 重构代码时,使用它能很容易发现问题。

3.三定律
如果对默认方法的工作原理, 特别是在多重继承下的行为还没有把握, 如下三条简单的定律可以帮助大家。
1. 类胜于接口。 如果在继承链中有方法体或抽象的方法声明, 那么就可以忽略接口中定义的方法。
2. 子类胜于父类。 如果一个接口继承了另一个接口, 且两个接口都定义了一个默认方法,那么子类中定义的方法胜出。
3. 没有规则三。 如果上面两条规则不适用, 子类要么需要实现该方法, 要么将该方法声明为抽象方法。

其中第一条规则是为了让代码向后兼容。

4.Optional

                //①创建某个值的 Optional 对象
		Optional<String> a=Optional.of("a");
		System.out.println(a.get());
		
		//②创建一个空的 Optional 对象, 并检查其是否有值
		Optional<String> b =Optional.empty();
		System.out.println(b.isPresent());
		
		Optional<String> c =Optional.ofNullable(null);
		System.out.println(c.isPresent());
		
		//③使用 orElse 和 orElseGet 方法
		System.out.println(Objects.equals("b", b.orElse("b")));
		System.out.println(Objects.equals("c", c.orElseGet(()->"c")));

5.练习题
(1) 在例 4-25 所示的 Performance 接口基础上, 添加 getAllMusicians 方法, 该方法返回包含所有艺术家名字的 Stream, 如果对象是乐队, 则返回每个乐队成员的名字。 例如, 如果 getMusicians 方法返回甲壳虫乐队, 则 getAllMusicians 方法返回乐队名和乐队成员,如约翰 · 列侬、 保罗 · 麦卡特尼等。
例 4-25 表示音乐表演的接口
// 该接口表示艺术家的演出— — 专辑或演唱会 
public interface Performance {
public String getName();
public Stream<Artist> getMusicians();

 

}

 

答案:

service:

package com.mmmm.service;

import java.util.stream.Stream;

import com.mmmm.model.Artist;

public interface Performance {
	public String getName();
	public Stream<Artist> getMusicians();
	public Stream<String> getAllMusicians();
	
}

serviceImpl

package com.mmmm.service.impl;

import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

import com.mmmm.model.Artist;
import com.mmmm.service.Performance;

public class PerformanceImpl implements Performance{

	private List<Artist> musicians;
	private String artistName;
	public void setName(String artistName) {
		this.artistName = artistName;
	}

	public void setMusicians(List<Artist> musicians) {
		this.musicians = musicians;
	}

	@Override
	public String getName() {
		
		return artistName;
	}

	@Override
	public Stream<Artist> getMusicians() {
		
		return musicians.stream()
				.filter(artist->Objects.equals(artist.getName(), artistName));
	}

	@Override
	public Stream<String> getAllMusicians() {
		
		Stream<Artist> musicians =getMusicians();
		
		return musicians.map(artist->artist.getName()+""+artist.getMembers());
	}

}

测试方法

package com.mmmm.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.mmmm.model.Artist;
import com.mmmm.service.impl.PerformanceImpl;

public class Test_05 {

	public static void main(String[] args) {
		List<Artist> musicians=new ArrayList<Artist>();
		musicians.add(new Artist("JiaKeChong",Arrays.asList("zhangsan","lisi","wangwu") , "Americ"));
		musicians.add(new Artist("TFBOYS",Arrays.asList("wangyuan","wang","yiyangqianxi") , "China"));
		musicians.add(new Artist("xiha",Arrays.asList("lili","tom") , "Italy"));
		musicians.add(new Artist("yangmi",null , "Italy"));
		PerformanceImpl impl=new PerformanceImpl();
		impl.setMusicians(musicians);
		impl.setName("JiaKeChong");
		System.out.println(impl.getAllMusicians().collect(Collectors.toList()));

	}

}

(2) 例 4-26 所示的 Artists 类表示了一组艺术家, 重构该类, 使得 getArtist 方法返回一个 Optional<Artist> 对象。 如果索引在有效范围内, 返回对应的元素, 否则返回一个空Optional 对象。 此外, 还需重构 getArtistName 方法, 保持相同的行为。例 4-26 包含多个艺术家的 Artists 类

public class Artists {
				private List<Artist> artists;
				public Artists(List<Artist> artists) {
				this.artists = artists;
				}
				public Artist getArtist(int index) {
				if (index < 0 || index >= artists.size()) {
				indexException(index);
				}
				return artists.get(index);
				}
				private void indexException(int index) {
				throw new IllegalArgumentException(index +
				"doesn't correspond to an Artist");
				}
				public String getArtistName(int index) {
				try {
				Artist artist = getArtist(index);
				return artist.getName();
				} catch (IllegalArgumentException e) {
				return "unknown";
				}
				}
				}

答案:

package com.mmmm.model;

import java.util.List;
import java.util.Optional;

public class Artists {

	private List<Artist> artists;

	public Artists(List<Artist> artists) {
		this.artists = artists;
	}

	public Optional<Artist> getArtist(int index) {

		if (index < 0 || index >= artists.size()) {

			indexException(index);
			return Optional.empty();

		}

		return Optional.of(artists.get(index));
	}

	private void indexException(int index) {

		throw new IllegalArgumentException(index + "doesn't correspond to an Artist");

	}

	public String getArtistName(int index) {

		try {

			Optional<Artist> artist = getArtist(index);

			return artist.get().getName();

		} catch (IllegalArgumentException e) {

			return "unknown";

		}
	}
}

总结:

 

Optional 是为核心类库新设计的一个数据类型, 用来替换 null 值。 人们对原有的 null 值有很多抱怨, 甚至连发明这一概念的 Tony Hoare 也是如此, 他曾说这是自己的一个“ 价值连城的错误”。 作为一名有影响力的计算机科学家就是这样: 虽然连一毛钱也见不到, 却也可以犯一个“ 价值连城的错误”。

人们常常使用 null 值表示值不存在, Optional 对象能更好地表达这个概念。 使用 null 代表值不存在的最大问题在于表值不存在的最大问题在于 NullPointerException。 一旦引用一个存储 null 值的变量, 程序会立即崩溃。 使用 Optional 对象有两个目的: 首先, Optional 对象鼓励程序员适时检查变量是否为空, 以避免代码缺陷; 其次, 它将一个类的 API 中可能为空的值文档化, 这比阅读实现代码要简单很多。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值