java8+stream+remove_JAVA8你只需要知道这些(2)

前言

上篇文章我们讲了JAVA8中接口和匿名内部类的一些新特性。这篇文章我们将继续深入的研究JAVA8。

1.Function包

在JAVA8中引入了java.util.function包,这个包里面全是接口,其中有四个接口值得我们注意:

1.Function 功能型接口

public interface Function {

R apply(T t);

}

需要注意的是@FunctionalInterface注解说明这是一个函数式接口,函数式接口中只能包含一个抽象方法,如果多于一个会报错,但是可以有默认方法,静态方法。

从Function接口来看,该接口接收一个参数返回一个参数。

2.Consumer 消费型接口

public interface Consumer {

void accept(T t);

}

Consumer接口接收一个参数,但是没有返回值。

3.Supplier 供给型接口

public interface Supplier {

/**

* Gets a result.

*

* a result

*/

T get();

}

Supplier接口不接收参数,但是有返回值。

4.Predicate 断言型接口

public interface Predicate {

boolean test(T t);

}

Predicate接口接收一个参数,返回一个boolean类型。

知道这4个接口有什么用呢?这4个接口是我们接下来要讲的stream的基础,在stream中,有大量的方法用到了以上的接口。

2.Stream

Stream API真正的把函数式编程风格引入了JAVA。Stream主要用来对数据进行处理,尤其是对集合数据的处理。Stream Api对应的是java.util.stream包,在这个包下面有一个Stream接口,是我们主要研究的对象。

我们先来看看创建Stream的几种方式:

//1.使用Stream接口中的方法

Stream stream = Stream.of("1", "2", "3");

// 2. 使用Arrays.stream方法

String [] strs = new String[] {"1", "2", "3"};

stream = Arrays.stream(strs );

// 3. 使用Collection接口中的stream方法

List list = Arrays.asList(strs );

stream = list.stream();

但是不论是用哪一种方式创建Stream,其内部都是通过以下代码实现:

public static Stream stream(Spliterator spliterator, boolean parallel) {

Objects.requireNonNull(spliterator);

return new ReferencePipeline.Head<>(spliterator,

StreamOpFlag.fromCharacteristics(spliterator),

parallel);

}

知道如何创建Stream以后,我们就要开始使用它:

String [] strs = new String[] {"java", "android", "ios"};

Arrays.stream(strs).filter((x)-> x.length()>3).forEach(System.out::println);

以上代码很简单,首先创建了一个String数组,然后通过Arrays.stream创建一个Stream,再通过filter方法把长度大于3的字符串过滤出来,最后通过System.out::println输出到控制台。

到这里就不得不提到Stream的操作了:

1af96c309eb6ea621c0dc0475e966995.png

Stream操作分为中间操作和终端操作,中间操作就比如上面的filter方法,终端操作就比如上面的forEach方法。Stream的中间操作会惰性执行,只有执行到终端操作了才会立即去处理。这样的好处就是可以提升性能。

中间操作又分为有状态和无状态两种,有状态的操作必须等到所有元素处理完之后才知道最终结果,比如排序操作,在读取完所有元素前,就不能确定排序的结果。而无状态的操作中,元素的处理不受前面元素的影响,比如filter操作就是无状态的,当前元素的操作不会受到前面元素的影响。

终端操作也分为非短路操作和短路操作,短路操作即不用处理全部元素就可以返回结果,比如anyMatch方法,找到第一个满足条件的元素就返回。非短路操作就是要处理完全部元素才可以返回结果。

中间操作包括:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

终端操作包括:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

3.方法引用

可能细心的朋友已经发现了,在以上我们的代码中使用了System.out::println而不是System.out.prinlnt。这种语法我们以前似乎没有见过?对,它叫方法引用,这也是JAVA8中的新特性,我们来看看它的语法:

1.引用静态方法: 类名称::静态方法名

2.引用普通方法:  实例化对象名::普通方法名

3.引用特定类方法:  特定类::普通方法名

4.引用构造方法:  类名称::new

你可能会说,不就是把以前的方法调用由.变成了::么?有什么可稀奇的?方法引用跟以前方法调用最大的区别在于,你可以用另外一个方法来引用该方法,说通俗一点就是可以给方法取一个别名,例如:

范例:把Int型转换为String

interface Action

{

R convert(P p);

}

public static void main(String[]args){

Action a=String::valueOf;

String str=a.convert(123);

System.out.println(str);

}

在上面代码中,我们首先定义了函数式接口,关于函数式接口的定义我们上篇文章已经说过了,要是忘记了可以再回上篇文章看看。Action接口中有convert方法,接收一个参数,返回一个值。这跟我们String类中的valueOf方法一样,valueOf方法也是传入一个参数,返回一个值:

public static String valueOf(int i)

所以我们就可以用convert来引用valueOf方法,可以看见我们的convert方法是没有被实现的,他的功能完全取决于valueOf方法。并且因为valueOf方法是静态的,所以我们按照方法引用的语法,可以用类名::静态方法名直接引用。

范例:把小写字符串转换为大写

interface Action{

R convert();

}

public static void main(String[]args){

Action a="abc"::toUpperCase;

String str=a.convert();

System.out.println(str);

}

在上面代码中,我们通过方法引用把小写的abc,转换为大写的ABC,在使用方法引用的时候,我们用了"abc"这就是String类的一个实例,而toUpperCase的定义是一个普通方法:

public String toUpperCase()

范例:比较两个字符的大小

interface Action

{

int convert(P p1,P p2);

}

public static void main(String[]args){

Action a=String::compareTo;

System.out.println(a.convert("a","b"));

在以上代码中我们引用了compareTo方法来比较两个字符串的大小。但是我们来看该方法的定义:

public int compareTo(String anotherString)

它竟然不是静态方法,我们却用类名直接引用,这是为什么?正常情况下,类名::方法名,这个方法肯定是静态方法。但是为什么这里普通方法也可以呢?这就要分析一下compareTo这个方法了,这个方法是两个字符串进行对比,正常情况下的写法应该是"a".compareTo("b"),对应的方法引用应该是"a"::compareTo。

如果是这样,我们定义函数式接口的时候,就应该定义成以下这样:

interface Action

{

int convert(P p1);

}

public static void main(String[]args){

Action a="a"::compareTo;

System.out.println(a.convert("b"));

}

如果接口定义成这样,就可以使用"a"::compareTo这种形式的方法引用。到这里聪明的你应该明白,为什么在上面可以通过类名引用普通方法了吧?我们想想在String类里面除了compareTo还有其他方法没?很多是不是?equals,endsWith都属于,所以他们都可以通过把方法参数定义为两个,然后用类名::方法名。

class ShopCar{

private String name;

private double price;

private int amount;

public ShopCar(String name,double price,int amount){

this.name=name;

this.price=price;

this.amount=amount;

}

public int getAmount() {

return amount;

}

public String getName() {

return name;

}

public double getPrice() {

return price;

}

public String toString() {

// TODO Auto-generated method stub

return "商品名:"+this.name+" 价格:"+this.price+" 数量:"+this.amount;

}

}

interface Action{

C create(String name,double price,int amount);

}

public static void main(String[]args){

Action a=ShopCar :: new;

ShopCar car=a.create("苹果",5,2);

System.out.println(car);

}

以上代码演示了如何通过类名称::new 来构造一个ShopCar对象。

结语:

今天的文章主要讲了JAVA8新引入的两个包和方法引用,其中Function包是基础,大家一定要多多理解。Stream包是函数式编程风格的主要提现,下一篇文章我们会着重介绍Stream接口中的方法。

如果你觉得本篇文章帮助到了你,希望大爷能够打赏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值