*Lambda表达式
新的日期API——Date time
引入Optional——防止空指针异常
*接口的默认方法和静态方法
*新增方法引用格式
*新增Stream类
注解相关的改变
支持并行(Parallel)数组
对并发类(Concurrency)的扩展
JavaFx
例:
@FunctionalInterface
public interface MyFunctionalInterface {
/**
* 有且仅有一个抽象方法
*/
void method();
/**
* 静态方法
*/
static void get(){
}
/**
* 实现接口方法体
*/
default void defaultMethod() {
System.out.println("接口默认方法!");
}
}
函数式思想:只关注做什么,不关注怎么做。
格式:
public interface 接口名称{
返回值 方法名称();
}
三要素:参数、箭头、代码 即 (参数1,参数2…)->{}
解决的问题:有些场景下的代码执行后结果不一定会被使用,造成性能浪费
private void log(int level,String msg) {
if(level == 1){
System.out.println(msg);
}
}
@Test
public void testStringConcat() {
String str1 = "hhh";
String str2 = "csl";
String str3 = "csl123";
log(1,str1+str2+str3);
}
存在问题:无论level是否满足条件,log的第二个参数的那三个字符串一定会首先进行拼接并传入方法,然后才开始判断level。
private void log2(int level, MessageBuilder builder){
if (level == 1) {
System.out.println(builder.builderMessage());
}
}
/**
* 使用Lambda表达式实现字符串的拼接,并验证了延时执行
*/
@Test
public void testStringConcatLambda() {
String str1 = "hhh";
String str2 = "csl";
String str3 = "csl123";
// Lambda方式进行延时执行
// 如果不符合要求,lambda将不会执行;即level=2时不会执行
log2(1, () -> str1+str2+str3);
}
如果方法的参数是一个函数式接口类型,那么就可以使用Lambda表达式进行替代。使用Lambda表达式作为方法参数,就是使用函数式接口作为方法参数。 例如 java.lang.Runnable接口就是一个函数式接口,假设有一个 startThread方法使用该接口作为参数,那么就可以使用Lambda进行传参。这种情况其实和Thread类的构造方法参数为Runnable没有本质区别。
有参数,且需要返回值。
@FunctionalInterface
public interface Function<T, R> {
/**
*根据类型T的参数获取类型R的结果
*/
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
*先进行操作再进行操作
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
public class FunctionTest {
@Test
public void testFunction(){
int num = parseInteger(
Integer::parseInt,
"10"
);
System.out.println(num);
}
private Integer parseInteger(Function<String,Integer> function,String str){
return function.apply(str);
}
/**
* 自定义函数模型拼接
*/
@Test
public void testAge(){
String str = "csl,16";
int ageNum = getAgeNum(
s -> s.split(",")[1],
Integer::parseInt,
i -> i + 100, str
);
System.out.println(ageNum);
}
/**
*
* @param one 将字符串截取数字年龄部分,得到字符串
* @param two 将上一步的字符串转换为int类型的数字
* @param three 将上一步的int数字累加100得到的结果
* @param str 处理的字符串
* @return 返回处理结果
*/
private int getAgeNum(Function<String,String> one,Function<String,Integer> two,Function<Integer,Integer> three,String str) {
return one.andThen(two).andThen(three).apply(str);
}
}
无参数,指定返回值类型,经常用于只关注过程的代码。
@FunctionalInterface
public interface Supplier<T> {
/**
* 用来获取一个泛型参数指定类型的对象数据,即对外提供
*/
T get();
}
public class SupplierTest {
@Test
public void testSupplier() {
User user = getUser(User::new);
System.out.println(user);
}
private User getUser(Supplier<User> supplier){
return supplier.get();
}
/**
* 获取最小值
*/
@Test
public void testMin() {
int[] arr = {12,54,65,43,76,98,9};
int minNum = getMin(() -> {
int min = arr[0];
for (int item : arr
) {
if (item < min) {
min = item;
}
}
return min;
});
System.out.println(minNum);
}
private int getMin(Supplier<Integer> supplier){
return supplier.get();
}
}
不需要返回值,有参数,经常用于迭代。
@FunctionalInterface
public interface Consumer<T> {
/**
*消费一个指定泛型的数据
*/
void accept(T t);
/**
*参数和返回值都是Consumer类型;首先做一个操作再做一个操作
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
public class ConsumerTest {
/**
* 单个参数
*/
@Test
public void testConSummerTest(){
User user = new User();
setUserDefaultSex(u -> u.setSex("男"),user);
System.out.println(user);
}
private void setUserDefaultSex(Consumer<User> conSummer,User user) {
conSummer.accept(user);
}
/**
* 一个参数
*/
@Test
public void testConSummerTest2(){
User user = new User();
setUserDefaultNameAndSex(u -> u.setSex("男"),u->u.setName("张三"),user);
System.out.println(user);
}
private void setUserDefaultNameAndSex(Consumer<User> one,Consumer<User> two,User user) {
one.andThen(two).accept(user);
}
/**
* 多个参数
*/
@Test
public void testConSummerTest3(){
User user = new User();
setUserDefault(u -> u.setSex("男"),u->u.setName("张三"),u->u.setId(1),user);
System.out.println(user);
}
private void setUserDefault(Consumer<User> one,Consumer<User> two,Consumer<User> three,User user) {
one.andThen(two).andThen(three).accept(user);
}
}
返回true/false,经常用于判断。
@FunctionalInterface
public interface Predicate<T> {
/**
*用于条件判断的场景
*/
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);
}
}
public class PredicateTest {
/**
* 一个条件
*/
@Test
public void testPredicate() {
strLongThan(
s->s.length()>5,"实例"
);
}
private void strLongThan(Predicate<String> predicate,String str) {
boolean flag = predicate.test(str);
System.out.println("判断结果:"+flag);
}
/**
* 两个条件
*/
@Test
public void testSuccess(){
successThan(
s->s.contains("高"),s->s.contains("帅"),"高富"
);
}
private void successThan(Predicate<String> one,Predicate<String> two,String str) {
boolean flag = one.and(two).test(str);
System.out.println("强吗:"+flag);
}
/**
* 集合筛选
*/
@Test
public void testFilter() {
String[] array = {"迪丽热巴,女","马儿扎哈,男","地瓜嘎嘎,男","略略略,女"};
List<String> list = filter(
s -> s.split(",")[0].length() == 4,
s -> "男".equals(s.split(",")[1]), array
);
System.out.println(list);
}
private List<String> filter(Predicate<String> one,Predicate<String> two,String[] arr){
List<String> list = new ArrayList<>(8);
for (String s: arr
) {
boolean flag = one.and(two).test(s);
if (flag){
list.add(s);
}
}
return list;
}
}
方法引用符:::(双冒号)
专注于做什么,而不是怎么做;解决集合中的常见问题。
1.获取流
List<String> list = new ArrayList<>(8);
Set<String> set = new HashSet<>(8);
Map<String,Object> map= new HashMap<String, Object>(8);
String[] array = {"陈西瓜","张收到","呜哈哈","陈开心","王开心","张开心","样开心","李难过"};
Collection接口实现类获取流
// Collection接口的实现类获取流
Stream<String> streamList = list.stream();
Stream<String> streamSet = set.stream();
}
Map接口实现类获取流
// Map接口的实现类获取流
Stream<String> streamKey = map.keySet().stream();
Stream<Object> streamValue = map.values().stream();
数组获取流
// 数组获取流
Stream<String> streamArray = Stream.of(array);
2.流的常用方法
List<String> list = new ArrayList<>(8);
list.add("陈西瓜");
list.add("张收到");
list.add("呜哈哈");
list.add("陈开心");
list.add("王开心");
list.add("张开心");
list.add("杨开心");
list.add("李难过");
list.stream().forEach(System.out::print);
list.stream().filter(e->e.contains("开心"));
list.stream().map(e -> e.substring(2));
list.stream().count();
list.stream().limit(n);
list.stream().skip(n);
list.stream().skip(n).limit(n);
Stream.concat(one, two);
list.stream().collect(Collectors.toList());
关于流的常用方法使用案例:
@Test
public void testCommonMethod() {
List<String> list = new ArrayList<>(8);
list.add("陈西瓜");
list.add("张收到");
list.add("呜哈哈");
list.add("陈开心");
list.add("王开心");
list.add("张开心");
list.add("杨开心");
list.add("李难过");
System.out.print("逐一处理:");
list.stream().forEach(System.out::print);
System.out.print("\n过滤:");
list.stream().filter(e->e.contains("开心")).forEach(System.out::print);
System.out.print("\n映射(将stream里面的内容映射到另一个stream中):");
list.stream().map(e -> e.substring(2)).forEach(System.out::print);
System.out.print("\n统计个数. 即list.size(): ");
System.out.print(list.stream().count());
System.out.print("\n取用前3个: ");
list.stream().limit(3).forEach(System.out::print);
System.out.print("\n跳到前1个:");
list.stream().skip(1).forEach(System.out::print);
System.out.print("\n通过limit+skip可以实现分页效果:");
list.stream().skip(2).limit(2).forEach(System.out::print);
System.out.print("\n合并两个流:");
Stream<String> one = list.stream().skip(0).limit(2);
Stream<String> two = list.stream().skip(5).limit(2);
Stream.concat(one, two).forEach(System.out::print);
System.out.print("\n将流转为集合:");
List<String> collect = list.stream().collect(Collectors.toList());
collect.forEach(System.out::print);
}