java8基本概念

来源:互联网 发布:电信大数据应用案例 编辑:程序博客网 时间:2024/06/06 14:07

函数式接口

只定义了一个抽象方法的接口就是函数式接口。

知识点回顾:

①接口中的方法默认为public abstract,即默认就是公共的抽象方法。

函数描述符

官网解释:函数式接口中的抽象方法就是函数描述符
或者说是它的签名就是函数描述符。

具体点,比如Runable这个接口里面只有一个方法run

@Overridepublic void run() {}

我们可以看到这个方法没有参数,也没有返回值。
那么我们就可以描述这个方法什么也不接受,什么也不返回。

①函数式接口的抽象方法的签名称为函数描述符
②抽象方法的签名可以描述Lambda表达式的签名。


因为我们在使用Lambda表达式时,总是要先定义一个函数式接口。这样很麻烦。
所以java8的设计者,已经提前帮我们设计好了几种常用的接口。

Predicate

java.util.function.Predicate<T>接口定义了一个名叫test的抽象方法,它接受泛型T对象,并返回一个boolean

@FunctionalInterfacepublic interface Predicate<T>{    boolean test(T t);}public static <T> List<T> filter(List<T> list, Predicate<T> p) {    List<T> results = new ArrayList<>();    for(T s: list){        if(p.test(s)){        results.add(s);        }    }    return results;}Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();//使用List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);

Consumer

java.util.function.Consumer<T>定义了一个名叫accept的抽象方法,它接受泛型T的对象,没有返回(void)。你如果需要访问类型T的对象,并对其执行某些操作,就可以使用这个接口。

@FunctionalInterfacepublic interface Consumer<T>{    void accept(T t);}public static <T> void forEach(List<T> list, Consumer<T> c){    for(T i: list){        c.accept(i);    }}//使用forEach(    Arrays.asList(1,2,3,4,5),    (Integer i) -> System.out.println(i));

Function

java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个泛型T的对象,并返回一个泛型R的对象。

@FunctionalInterfacepublic interface Function<T, R>{    R apply(T t);}public static <T, R> List<R> map(List<T> list, Function<T, R> f) {    List<R> result = new ArrayList<>();    for(T s: list){        result.add(f.apply(s));    }    return result;}// [7, 2, 6]List<Integer> l = map(Arrays.asList("lambdas","in","action"),(String s) -> s.length());

以上者三个是泛型函数式接口。但是java除了引用类型,还有原始类型(int, double, byte,char)。但是泛型(比如Consumer<T>中的T)只能绑定到引用类型。这是由泛型内部的实现方式造成的。因此,在Java里有一个将原始类型转换为对应的引用类型的机制。这个机制叫作装箱(boxing)。相反的操作,也就是将引用类型转换为对应的原始类型,叫作拆箱(unboxing)。Java还有一个自动装箱机制来帮助程序员执行这一任务:装箱和拆箱操作是自动完成的。

但这在性能方面是要付出代价的。装箱后的值本质上就是把原始类型包裹起来,并保存在堆里。因此,装箱后的值需要更多的内存,并需要额外的内存搜索来获取被包裹的原始值。

Java 8为我们前面所说的函数式接口带来了一个专门的版本,以便在输入和输出都是原始类型时避免自动装箱的操作。

比如,在下面的代码中,使用IntPredicate就避免了对值1000进行装箱操作,但要是用Predicate<Integer>就会把参数1000装箱到一个Integer对象中。

public interface IntPredicate{    boolean test(int t);}IntPredicate evenNumbers = (int i) -> i % 2 == 0;evenNumbers.test(1000);  ----> true(无装箱)Predicate<Integer> oddNumbers = (Integer i) -> i % 2 == 1;oddNumbers.test(1000); ----> false(装箱)

一般来说,针对专门的输入参数类型的函数式接口的名称都要加上对应的原始类型前缀,比如DoublePredicateIntConsumerLongBinaryOperatorIntFunction等。Function接口还有针对输出参数类型的变种:ToIntFunction<T>IntToDoubleFunction等。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 生完孩子后腰疼的厉害怎么办 眼睛进东西了弄不出来怎么办 18k金不给换黄金怎么办 我22岁欠了10万怎么办 1岁宝宝又吐又拉怎么办 月经10天了还没干净怎么办 舌头有异味怎么办是有口臭吗 快8个月羊水破了怎么办 25岁欠了50万债怎么办 28岁血压高150低压110怎么办 苹果6的4g网络慢怎么办 一个月染了6次头怎么办 五0二干在衣服上怎么办 刚怀孕见红了肚子不痛怎么办 我有外遇了老婆不离婚怎么办 套了牙套的牙疼怎么办 我鼻子上有很多螨虫和黑头怎么办 鱼刺卡在喉咙怎么办最有效的办法 脚被蚊子咬了很痒怎么办 好压7z密码忘了怎么办 4g卡显示2g网络怎么办 过塑机把纸吞了怎么办 红米1s开不了机怎么办 跟老婆吵架闹的要离婚该怎么办 充了q币没有到账怎么办 9个月宝宝吃了盐怎么办 红米4x开不了机怎么办 鱼身上有红斑像出血了怎么办 草鱼身上有红斑像出血了怎么办 宝宝屁眼红的破皮了怎么办 孩子身上起红疙瘩很痒怎么办 久而不射,但软了怎么办 盆底综合肌力1级怎么办 头发掉的厉害怎么办吃什么好 给蜂蛰了肿了痒怎么办 小米手环2没电了怎么办 小米手环2不亮了怎么办 红米3s无限重启怎么办 乐视手机1s卡顿怎么办 老公出轨了怎么办你会选择离婚吗 c盘和d盘换换了怎么办