【Java】Stream流和方法引用

1 Stream流

1.1 Stream流优化过滤集合

传统方式

  1. 用一个循环过滤姓张的人
  2. 用一个循环过滤名字长度大于2的人
    public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("张三三");list.add("张四四");list.add("李四四");ArrayList<String> newlist = new ArrayList<>();for(String s: list){if(s.startsWith("张")&&s.length()>2){listWithZhang.add(s);}}for(String s: newlist){System.out.println(s);}}

Stream流
JDK1.8后出现,关注做什么,而不是怎么做

	public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("张三三");list.add("张四四");list.add("李四四");list.stream().filter((name)->name.startsWith("张")).filter((name)->name.length()>2).forEach((name)->{System.out.println(name);});}

1.2 流式思想概述

拼接流式模型:建立一个生产线,按照生产线来生产商品。

当使用一个流的时候,通常包括三个基本步骤:

  1. 获取一个数据源(source)→
  2. 数据转换→
  3. 执行操作获取想要的结果.

每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。

1.3 获取流

java.util.stream.Stream<T> 是Java 8新加入的最常用的流接口。
(这并不是一个函数式接口。)

获取一个流有以下几种常用的方式:

  1. 所有的Collection集合都可以通过 stream 默认方法获取流;
  2. Stream 接口的静态方法 of 可以获取数组对应的流。
    public static void main(String[] args) {//集合调用stream方法可以获得ArrayList<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();//数组可以用Stream.of获得Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5, 6);Integer[] arr = {1, 2, 3, 5};Stream<Integer> steam7 = Stream.of(arr);}   

流的特点:Stream流属于管道流,只能使用一次,第一个流使用完毕就会关闭,这个流就不可以再调用其他方法了。

1.4 常用方法

流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:

  1. 延迟方法:返回值类型仍然是Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为延迟方法。)
  2. 终结方法:返回值类型不再是Stream 接口自身类型的方法,因此不再支持类似StringBuilder 那样的链式调用。(例如:count 和forEach方法)。

forEach方法:forEach的参数是Consumer

    //forEach的参数的Consumer//Consumer接口是一个消费型的函数式接口,可以传递lambda表达式消费数据public static void main(String[] args) {Stream<String> stream = Stream.of("张三", "李四", "王五");stream.forEach(name-> System.out.println(name));}

filter方法:filter的参数是Predicate,用于将一个流转换成另一个子集流

    //forEach的参数是该接口接收一个Predicate//函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。//test方法将会产生一个boolean值结果,代表指定的条件是否满足。//如果结果为true,那么Stream流的filter 方法//将会留用元素;如果结果为false,那么filter 方法将会舍弃元素。public static void main(String[] args) {Stream<String> stream = Stream.of("张三", "张四","李四", "王五");Stream<String> stream1 = stream.filter((name) -> {return name.startsWith("张");});stream1.forEach(name-> System.out.println(name));}

map方法
如果需要将流中的元素映射到另一个流中,可以用map。可以将T类型的流转换为R类型的流。java.util.stream.Function 函数式接口,其中唯一的抽象方法为:apply。这可以将一种T类型转换成为R类型,而这种转换的动作,就称为“映射”。

将integer类型转换为string类型

    public static void main(String[] args) {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);Stream<String> stream2 = stream.map((Integer i) -> {return String.valueOf(i);});stream2.forEach((s)-> System.out.println(s));}

count方法
用于统计Stream流中的元素个数。正如旧集合Collection 当中的size 方法一样,流提供count 方法来数一数其中的元素个数。count方法返回值是long类型的整数,是终结方法,,之后不能再继续调用其他方法。

    public static void main(String[] args) {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);long count = stream.count();System.out.println(count);}

limit方法:可以对流进行截取。参数是long类型的整数。属于延迟方法,可以继续调用其他方法。如果集合当前长度大于参数则进行截取;否则不进行操作,即还是原流。

    public static void main(String[] args) {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);stream.limit(3).forEach((num)-> System.out.println(num));}

skip方法:可以跳过前几个元素,获取一个截取之后的新流。参数超过元素个数,返回空流。

    public static void main(String[] args) {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);stream.skip(3).forEach((num)-> System.out.println(num));}

concat方法:组合两个流为一个流。concat是静态方法,通过接口名调用。

    public static void main(String[] args) {Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5);Stream<String> stream2 = Stream.of("a","b","c","d");Stream.concat(stream1,stream2).forEach((s)-> System.out.println(s));}

1.5 练习-集合元素处理

现在有两个ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)依次进行以下若干操作步骤:
第一个队伍只要名字为3个字的成员姓名;
第一个队伍筛选之后只要前3个人;
第二个队伍只要姓张的成员姓名;
第二个队伍筛选之后不要前2个人;
将两个队伍合并为一个队伍;
根据姓名创建Person 对象;
打印整个队伍的Person对象信息。

Stream方式

    public static void main(String[] args) {ArrayList<Person> list1 = new ArrayList<>();list1.add(new Person("李白"));list1.add(new Person("杜甫"));list1.add(new Person("李清照"));list1.add(new Person("王勃"));list1.add(new Person("刘禹锡"));list1.add(new Person("辛弃疾"));list1.add(new Person("龚自珍"));ArrayList<Person> list2 = new ArrayList<>();list2.add(new Person("李四"));list2.add(new Person("王五"));list2.add(new Person("张一"));list2.add(new Person("张二"));list2.add(new Person("张三"));Stream<Person> newlist1 = list1.stream().filter((person) -> {return person.getName().length() == 3;}).limit(3);Stream<Person> newlist2 = list2.stream().filter((person) -> {return person.getName().startsWith("张");}).skip(2);Stream.concat(newlist1, newlist2).forEach((person)-> System.out.println(person));}

2 方法引用

2.1 应用:简化lambda

双冒号:: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。

例如上方代码中的最后一句可以等价为:

Stream.concat(newlist1, newlist2).forEach((person)-> System.out.println(person));
Stream.concat(newlist1, newlist2).forEach(System.out::println);

2.2 通过对象名引用成员方法

自定义一个接口

public interface Printable {void print(String s);
}

自定义一个类及其成员方法

public class MethodRerObject {public void printUpperCaseString(String str){System.out.println(str.toUpperCase());}
}

测试

public class Test {//通过对象名引用成员方法//前提:对象名存在,成员方法存在public static void printString(Printable p){p.print("Hello");}public static void main(String[] args) {//用lambdaprintString((s)->{MethodRerObject obj = new MethodRerObject();obj.printUpperCaseString(s);});//方法引用优化//对象和成员方法都存在MethodRerObject obj = new MethodRerObject();printString(obj::printUpperCaseString);}
}

2.3 通过类名引用静态成员方法

定义一个函数式接口

@FunctionalInterface
public interface Calcable {int calAbs(int num);
}

定义一个方法传递接口和整数

public class Test {public static int method(int number, Calcable c){return c.calAbs(number);}public static void main(String[] args) {//调用method方法int result = method(-10, (num) -> Math.abs(num));System.out.println(result);//使用方法引用优化 Math存在 abs的静态方法也存在int result2 = method(-10, Math::abs);System.out.println(result2);}
}

2.4 通过super引用父类成员方法

定义函数式接口

public interface Greatable {void great();
}

定义父类

public class Human {public void sayHello(){System.out.println("Hello, i am human");}
}

定义子类

public class Man extends Human{@Overridepublic void sayHello(){System.out.println("Hello, i am man");}public void great(Greatable g){g.great();}public void show(){great(()->{Human h = new Human();h.sayHello();});//通过父类调用great(()->{super.sayHello();});//通过父类引用great(super::sayHello);}public static void main(String[] args) {new Man().show();}
}

2.5 通过this引用本类成员方法

public interface Richable {void buy();
}
public class Husband {public void buyHouse(){System.out.println("买房子");}public void marry(Richable r){r.buy();}public void soHappy(){//this和buyHouse都是以及存在的 可以直接用this来引用本类方法//marry(()->this.buyHouse());marry(this::buyHouse);}public static void main(String[] args) {new Husband().soHappy();}
}

2.6 类的构造器引用

自定义一个Person类,自定义一个创建Person的接口

public interface PersonBuilder {Person buildPerson(String name);
}
public class Test {public static void printName(String name, PersonBuilder pb){Person person = pb.buildPerson(name);System.out.println(person.getName());}public static void main(String[] args) {//调用method方法printName("张三",(name)->new Person(name));//使用方法引用优化 Person的构造方法已知 创建对象new已知printName("李四", Person::new);}
}

2.7 数组的构造器引用

@FunctionalInterface
public interface ArrayBuilder {int[] buiderArray(int length);
}
public class Test {public static int[] createArray(int len, ArrayBuilder ab){return ab.buiderArray(len);}public static void main(String[] args) {//调用method方法int[] array = createArray(10, (len) ->new int[len]);System.out.println(array.length);//使用方法引用优化lambda 已知创建的是int类型的数组 数组的长度已知int[] array1 = createArray(10, int[]::new);System.out.println(array1.length);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/480944.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python中输入和输出

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/xiaokang123456kao/article/details/73009480 </div><link rel"stylesheet" href"https://csdnimg.cn/release/phoenix/template/css/ck_htm…

刘志明 | 知识图谱及金融相关

本文转载自公众号&#xff1a;挖地兔&#xff0c;本文的作者刘志明先生也是 Tushare 的作者。 Tushare 是一个基于 Python 语言的免费、开源的财经数据接口包&#xff0c;可以为金融量化分析人员提供快速、整洁和多样的结构化数据&#xff0c;帮助量化投资人员节省数据采集和清…

模型训练太慢?显存不够用?这个算法让你的GPU老树开新花

一只小狐狸带你解锁NLP/ML/DL秘籍作者&#xff1a;小鹿鹿鹿&#xff0c;夕小瑶老板&#xff0c;咱们就一台Titan Xp&#xff0c;训不动BERT呀没钱买机器&#xff0c;自己想办法。委屈T^T我听说混合精度训练可以从算法上缓解这个问题&#xff1f;喵喵喵&#xff1f;&#xff1f;…

【Java】Junit、反射和注解的笔记

1 Junit 黑盒测试&#xff1a;不需要写代码&#xff0c;给输入值&#xff0c;看程序输出是否符合期望 白盒测试&#xff1a;需要写代码&#xff0c;关注程序具体的执行流程 Junit —> 白盒测试 步骤 定义一个测试类&#xff08;测试用例&#xff09; 【命名&#xff1a;类…

我对Spring的理解

1、什么是Spring&#xff1f; Spring是Java企业级应用的开源开发框架。Spring主要用来开发Java应用&#xff0c;但是有些扩展是针对构建J2EE平台的web应用。Spring框架目标是简化Java企业级应用开发&#xff0c;并通过POJO为基础的编程模型促进良好的编程习惯。 2、使用Spring…

k-means+python︱scikit-learn中的KMeans聚类实现( + MiniBatchKMeans)

版权声明&#xff1a;博主原创文章&#xff0c;微信公众号&#xff1a;素质云笔记,转载请注明来源“素质云博客”&#xff0c;谢谢合作&#xff01;&#xff01; https://blog.csdn.net/sinat_26917383/article/details/70240628 </div><link rel"stylesh…

想让推荐和搜索引擎更聪明?基于知识图谱的篇章标签生成

一只小狐狸带你解锁NLP/ML/DL秘籍正文来源&#xff1a;丁香园大数据NLP 老板&#xff5e;我们的推荐系统笨笨的你怎么对文档处理的这么糙&#xff01;抽个关键词就应付过去了&#xff1f;啊啊啊我错惹&#xff0c;那那&#xff0c;不用关键词用什么呢&#xff1f;知识图…

论文浅尝 | Dynamic Weighted Majority for Incremental Learning

Yang Lu , Yiu-ming Cheung , Yuan Yan Tang. Dynamic Weighted Majority for Incremental Learning ofImbalanced Data Streams with Concept Drift. In Proceedings of the Twenty-Sixth International Joint Conference on Artificial Intelligence (IJCAI-17)论文链接&…

【JavaWeb】数据库基础复习

1 MySQL 数据库特点&#xff1a; 持久化存储数据&#xff0c;数据库就是一个文件系统便于存储和管理数据使用统一的方式操作数据库 启动MySQL服务&#xff1a; 管理员cmd&#xff1a;net start mysql 停止MySQL服务&#xff1a; 管理员cmd&#xff1a;net stop mysql 打开服…

Python的多行输入与多行输出

因为在OJ上做编程&#xff0c;要求标准输入&#xff0c;特别是多行输入。特意查了资料&#xff0c;自己验证了可行性。if __name__ "__main__":strList []for line in sys.stdin: #当没有接受到输入结束信号就一直遍历每一行tempStr line.split()#对字符串利用空…

微服务Dubbo和SpringCloud架构设计、优劣势比较

一、微服务介绍 微服务架构是互联网很热门的话题&#xff0c;是互联网技术发展的必然结果。它提倡将单一应用程序划分成一组小的服务&#xff0c;服务之间互相协调、互相配合&#xff0c;为用户提供最终价值。虽然微服务架构没有公认的技术标准和规范或者草案&#xff0c;但业界…

搜索引擎核心技术与算法 —— 词项词典与倒排索引优化

一只小狐狸带你解锁NLP/ML/DL秘籍作者&#xff1a;QvQ老板&#xff5e;我会写倒排索引啦&#xff01;我要把它放进咱们自研搜索引擎啦&#xff01;我呸&#xff01;你这种demo级代码&#xff0c;都不够当单元测试的&#xff01;嘤嘤嘤&#xff0c;课本上就是这样讲的呀?!来来&…

论文浅尝 | Distant Supervision for Relation Extraction

Citation: Ji,G., Liu, K., He, S., & Zhao, J. (2017). Distant Supervision for RelationExtraction with Sentence-Level Attention and Entity Descriptions. Ai,3060–3066.动机关系抽取的远程监督方法通过知识库与非结构化文本对其的方式&#xff0c;自动标注数据&am…

使用sklearn做单机特征工程

目录 1 特征工程是什么&#xff1f;2 数据预处理  2.1 无量纲化    2.1.1 标准化    2.1.2 区间缩放法    2.1.3 标准化与归一化的区别  2.2 对定量特征二值化  2.3 对定性特征哑编码  2.4 缺失值计算  2.5 数据变换  2.6 回顾3 特征选择  3.1 Filte…

【JavaWeb】JDBC的基本操作和事务控制+登录和转账案例

1 JDBC操作数据库 1.1 连接数据库 首先导入jar包到lib public class JdbcDemo1 {public static void main(String[] args) throws ClassNotFoundException, SQLException {//1.注册驱动Class.forName("com.mysql.jdbc.Driver");//2.获取数据库连接对象Connection…

Restful、SOAP、RPC、SOA、微服务之间的区别

一、介绍Restful、SOAP、RPC、SOA以及微服务 1.1、什么是Restful&#xff1f; Restful是一种架构设计风格&#xff0c;提供了设计原则和约束条件&#xff0c;而不是架构&#xff0c;而满足这些约束条件和原则的应用程序或设计就是 Restful架构或服务。 主要的设计原则&#xf…

详解深度语义匹配模型DSSM和他的兄弟姐妹

一只小狐狸带你解锁NLP/ML/DL秘籍正文作者&#xff1a;郭耀华正文来源&#xff1a;https://www.cnblogs.com/guoyaohua/p/9229190.html前言在NLP领域&#xff0c;语义相似度的计算一直是个难题&#xff1a;搜索场景下Query和Doc的语义相似度、feeds场景下Doc和Doc的语义相似度、…

行业新闻 | 阿里发力知识图谱研究 悉数囊括顶尖学者探讨合作

12 月 20 日&#xff0c;阿里巴巴联合中国中文信息学会语言与知识计算专委会(KG专委)举办的知识图谱研讨会在杭州召开。研讨会由阿里巴巴集团副总裁墙辉&#xff08;花名&#xff1a;玄难&#xff09;主持&#xff0c;国内知识图谱领域多位顶级专家参加此次研讨会。在阿里巴巴持…

Kaggle入门,看这一篇就够了

New Update&#xff1a;之前发表了这篇关于 Kaggle 的专栏&#xff0c;旨在帮助对数据科学( Data Science )有兴趣的同学们更好的了解这个平台。专栏发表至今收到了不少的关注和肯定&#xff0c;还有很多小伙伴私信相关的问题。因此&#xff0c;我特邀了一位海外一线 Data Scie…

【JavaWeb】JDBC优化 之 数据库连接池、Spring JDBC

1 数据库连接池 为什么要使用数据库连接池&#xff1f; 数据库连接是一件费时的操作&#xff0c;连接池可以使多个操作共享一个连接使用连接池可以提高对数据库连接资源的管理节约资源且高效 概念&#xff1a;数据库连接池其实就是一个容器&#xff0c;存放数据库连接的容器…