JavaSE23-函数式接口&Stream流
1.函数式接口
1.1 函数式接口概述
概念
有且仅有一个抽象方法的接口
如何检测一个接口是不是函数式接口
@FunctionalInterface
放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败
注意事项
我们自己定义函数式接口的时候,@FunctionalInterface是可选的,就算我不写这个注解,只要保证满足函数式接口定义的条件,也照样是函数式接口。但是,建议加上该注解。
1.2 函数式接口作为方法的参数
1 public class RunnableDemo {
2 public static void main(String[] args) {
3 startRunnable(() -> {
4 System.out.println(Thread.currentThread().getName()+"启动了");
5 });
6 }
7
8 private static void startRunnable(Runnable r) {
9 new Thread(r).start();
10 }
11 }
在Runnable中有如下定义
1 @FunctionalInterface
2 public interface Runnable {
3 /**
4 * When an object implementing interface {@code Runnable} is used
5 * to create a thread, starting the thread causes the object's
6 * {@code run} method to be called in that separately executing
7 * thread.
8 * <p>
9 * The general contract of the method {@code run} is that it may
10 * take any action whatsoever.
11 *
12 * @see java.lang.Thread#run()
13 */
14 public abstract void run();
15 }
1.3 函数式接口作为方法的返回值
1 import java.sql.Connection;
2 import java.util.ArrayList;
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.Comparator;
6
7 public class getComparetorDemo {
8 public static void main(String[] args) {
9 ArrayList<String> list = new ArrayList<>();
10 list.add("aaa");
11 list.add("b");
12 list.add("dd");
13 list.add("cccc");
14
15 System.out.println("排序前:"+list);
16
17 Collections.sort(list,getComparetor());
18
19 System.out.println("排序后:"+list);
20 }
21
22 private static Comparator<String> getComparetor() {
23 return (s1,s2) -> s1.length() - s2.length();
24 }
25 }
1.4 常用函数式接口之Supplier
Supplier接口
Supplier接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用。
构造方法
| 方法名 | 说明 |
| T get() | 按照某种实现逻辑(由Lambda表达式实现)返回一个数据 |
返回字符串
1 import java.util.function.Supplier;
2
3 public class SupplierDemo {
4 public static void main(String[] args) {
5 System.out.println(useSup(
6 () -> "hello world"
7 ));
8 }
9
10 private static String useSup(Supplier<String> sup) {
11 return sup.get();
12 }
13 }
返回最大值
1 import java.util.function.Supplier;
2
3 public class SupplierDemo2 {
4 public static void main(String[] args) {
5 int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 21, 142, 11, 2241, 24};
6 int maxValue = useSup(() -> {
7 int max = arr[0];
8
9 for (int i = 0; i < arr.length; i++) {
10 if (max < arr[i]) {
11 max = arr[i];
12 }
13 }
14
15 return max;
16 });
17
18 System.out.println(maxValue);
19 }
20
21 private static Integer useSup(Supplier<Integer> sup) {
22 return sup.get();
23 }
24 }
1.5 常用函数式接口之Consumer
Consumer接口
Consumer接口也被称为消费型接口,它消费的数据的数据类型由泛型指定
常用方法
| 方法名 | 说明 |
| void accept(T t) | 对给定的参数执行此操作 |
| default Consumer andThen(Consumer after) | 返回一个组合的Consumer,依次执行此操作,然后执行after操作 |
1 import java.util.function.Consumer;
2
3 public class ConsumerDemo {
4 public static void main(String[] args) {
5 String[] list = {"1,绿巨人","2,钢铁侠","3,美国队长"};
6
7 printinfo(list,str -> System.out.print("序号"+str.split(",")[0]),str -> System.out.println(str.split(",")[1]));
8 }
9
10 public static void printinfo(String[] list, Consumer<String> con1,Consumer<String> con2){
11 for (String s : list){
12 con1.andThen(con2).accept(s);
13 }
14 }
15 }
1.6 常用函数式接口之Predicate
Predicate接口
Predicate接口通常用于判断参数是否满足指定的条件
| 方法名 | 说明 |
| boolean test(T t) | 对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回 一个布尔值 |
| default Predicate negate() | 返回一个逻辑的否定,对应逻辑非 |
| default Predicate and(Predicate other) | 返回一个组合判断,对应短路与 |
| default Predicate or(Predicate other) | 返回一个组合判断,对应短路或 |
1 import java.util.function.Predicate;
2
3 public class PredicateDemo {
4 public static void main(String[] args) {
5 boolean a = check("hello world",s -> s.length()<5);
6 System.out.println(a);
7
8 boolean b = uncheck("hello world",s -> s.length()<5);
9 System.out.println(b);
10 }
11
12 private static boolean check(String s , Predicate<String> pre){
13 return pre.test(s);
14 }
15
16 private static boolean uncheck(String s , Predicate<String> pre){
17 return pre.negate().test(s);
18 }
19 }
1.7 常用函数式接口之Function
Function接口
Function<t,r>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值
| 方法名 | 说明 |
| R apply(T t) | 将此函数应用于给定的参数 |
| default Function andThen(Function after) | 返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果 |
1 import java.util.function.Function;
2
3 public class FunctionDemo {
4 public static void main(String[] args) {
5 parseint("13729",s -> Integer.parseInt(s));
6 }
7
8 private static void parseint(String s, Function<String,Integer> fun) {
9 int i = fun.apply(s);
10 System.out.println(i);
11 }
12 }
2.Strem流
2.1 体验Stream流
1 import java.util.ArrayList;
2
3 public class FilterDemo {
4 public static void main(String[] args) {//将姓张且名字在两个字(不含两个)以上的名字加入另一个集合
5 ArrayList<String> names = new ArrayList<>();
6
7 names.add("张无忌");
8 names.add("赵敏");
9 names.add("张三丰");
10 names.add("张果老");
11 names.add("张国立");
12 names.add("铁拐李");
13 names.add("张赫");
14 names.add("张飞");
15 names.add("张翼德");
16 names.add("刘备");
17 names.add("关云长");
18 names.add("曹孟德");
19 names.add("吕轻侯");
20
21 ArrayList<String> zhanglist = new ArrayList<>();
22
23 names.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() >=3).forEach(System.out::println);
24 }
25 }
Stream流的好处
直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印
Stream流把真正的函数式编程风格引入到Java中
2.2 Stream流的常见生成方式
生成Stream流的方式
Collection体系集合
使用默认方法stream()生成流, default Stream stream()
Map体系集合
把Map转成Set集合,间接的生成流
数组
通过Stream接口的静态方法of(T... values)生成流
1 import java.util.*;
2 import java.util.stream.Stream;
3
4 public class CreateStream {
5 public static void main(String[] args) {
6 //Collection体系直接使用stream()
7 List<String> list = new ArrayList<>();
8 Stream<String> listStream = list.stream();
9
10 Set<String> set = new TreeSet<>();
11 Stream<String> setStream = set.stream();
12 //Map体系间接生成
13 Map<String,Integer> map = new HashMap<>();
14 Stream<String> keyStream = map.keySet().stream();
15 Stream<Integer> valueStream = map.values().stream();
16
17 Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
18 //数组使用Stream接口的of()
19 String[] nums = {"1","2","3","4"};
20 Stream<String> numStringStream = Stream.of(nums);
21 Stream<Integer> numStram = Stream.of(1,2,3,4,5);
22 }
23 }
2.3 Stream流中间操作方法
概念
中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。
常用方法
| 方法名 | 说明 |
| Stream filter(Predicate predicate) | 用于对流中的数据进行过滤 |
| Stream limit(long maxSize) | 返回此流中的元素组成的流,截取前指定参数个数的数据 |
| Stream skip(long n) | 跳过指定参数个数的数据,返回由该流的剩余元素组成的流 |
| static Stream concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
| Stream distinct() | 返回由该流的不同元素(根据Object.equals(Object) )组成的流 |
| Stream sorted() | 返回由此流的元素组成的流,根据自然顺序排序 |
| Stream sorted(Comparator comparator) | 返回由该流的元素组成的流,根据提供的Comparator进行排序 |
| Stream map(Function mapper) | 返回由给定函数应用于此流的元素的结果组成的流 |
| IntStream mapToInt(ToIntFunction mapper) | 返回一个IntStream其中包含将给定函数应用于此流的元素的结果 |
limit&skip
1 import java.util.ArrayList;
2
3 public class limitandskipDemo {
4 public static void main(String[] args) {
5 ArrayList<String> names = new ArrayList<>();
6
7 names.add("张无忌");
8 names.add("赵敏");
9 names.add("张三丰");
10 names.add("张果老");
11 names.add("张国立");
12 names.add("铁拐李");
13 names.add("张赫");
14 names.add("张飞");
15 names.add("张翼德");
16 names.add("刘备");
17 names.add("关云长");
18 names.add("曹孟德");
19 names.add("吕轻侯");
20
21 //输出前三个
22 names.stream().limit(3).forEach(System.out::println);
23 System.out.println("-------");
24 //跳过三个然后输出
25 names.stream().skip(3).forEach(System.out::println);
26 System.out.println("-------");
27 //跳过四个输出五个
28 names.stream().skip(4).limit(5).forEach(System.out::println);
29 }
30 }
concat&distinct
1 import java.util.ArrayList;
2 import java.util.stream.Stream;
3
4 public class concatanddistinctDemo {
5 public static void main(String[] args) {
6 ArrayList<String> names = new ArrayList<>();
7 names.add("张无忌");
8 names.add("赵敏");
9 names.add("张三丰");
10 names.add("张果老");
11 names.add("张国立");
12 names.add("铁拐李");
13
14 //截取前四个为流s1
15 Stream<String> s1 = names.stream().limit(4);
16 //跳过前两个为流s2
17 Stream<String> s2 = names.stream().skip(2);
18 //合并s1,s2
19 // Stream.concat(s1, s2).forEach(System.out::println);
20 //合并并去重
21 Stream.concat(s1, s2).distinct().forEach(System.out::println);
22 }
23 }
sort
1 import java.util.ArrayList;
2
3 public class sortDemo {
4 public static void main(String[] args) {
5 ArrayList<String> names = new ArrayList<>();
6 names.add("张无忌");
7 names.add("赵敏");
8 names.add("张三丰");
9 names.add("张果老");
10 names.add("张国立");
11 names.add("铁拐李");
12
13 names.stream().sorted((s1,s2) -> {
14 int num = s1.length()-s2.length();
15 int num2 = num == 0 ? s2.compareTo(s1) : num;
16 return num2;
17 }).forEach(System.out::println);
18 }
19 }
maptoInt
1 import java.util.ArrayList;
2
3 public class maptointDemo {
4 public static void main(String[] args) {
5 ArrayList<String> nums = new ArrayList<>();
6 nums.add("1");
7 nums.add("10");
8 nums.add("100");
9 nums.add("1000");
10 nums.add("10000");
11 nums.add("100000");
12
13 int result = nums.stream().mapToInt(Integer::parseInt).sum();
14 System.out.println(result);
15 }
16 }
count
1 import java.util.ArrayList;
2
3 public class countDemo {
4 public static void main(String[] args) {
5 ArrayList<String> names = new ArrayList<>();
6
7 names.add("张无忌");
8 names.add("赵敏");
9 names.add("张三丰");
10 names.add("张果老");
11 names.add("张国立");
12 names.add("铁拐李");
13 names.add("张赫");
14 names.add("张飞");
15 names.add("张翼德");
16 names.add("刘备");
17 names.add("关云长");
18 names.add("曹孟德");
19 names.add("吕轻侯");
20
21 long count = names.stream().filter(s -> s.startsWith("张")).count();
22 System.out.println(count);
23 }
24 }
练习
这里有两个集合,有6个男演员和6个女演员,要求:
男演员只要名字为3个字的前三人
女演员只要姓林的,并且不要第一个
把过滤后的男演员姓名和女演员姓名合并到一起
把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
Actor类
1 public class Actor {
2 private String name;
3
4 public Actor(String name) {
5 this.name = name;
6 }
7
8 public String getName() {
9 return name;
10 }
11
12 public void setName(String name) {
13 this.name = name;
14 }
15 }
实现类
1 import java.util.ArrayList;
2 import java.util.stream.Stream;
3
4 public class ActorControl {
5 public static void main(String[] args) {
6 ArrayList<String> man = new ArrayList<>();
7 ArrayList<String> woman = new ArrayList<>();
8
9 man.add("刘德华");
10 man.add("成龙");
11 man.add("周星驰");
12 man.add("周润发");
13 man.add("李小龙");
14 man.add("林正英");
15
16 woman.add("林青霞");
17 woman.add("关之琳");
18 woman.add("朱茵");
19 woman.add("林志玲");
20 woman.add("林心如");
21 woman.add("王祖贤");
22
23 //男演员只要名字为3个字的前三人
24 Stream<String> manStream = man.stream().filter(s -> s.length() == 3).limit(3);
25 //女演员只要姓林的,并且不要第一个
26 Stream<String> womanStream = woman.stream().filter(s -> s.startsWith("林")).skip(1);
27 //把过滤后的男演员姓名和女演员姓名合并到一起
28 Stream<String> stream = Stream.concat(manStream, womanStream);
29 //把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
30 stream.map(Actor::new).forEach(s -> System.out.println(s.getName()));
31 }
32 }
或者更简便的写法
1 import java.util.ArrayList;
2 import java.util.stream.Stream;
3
4 public class ActorControl {
5 public static void main(String[] args) {
6 ArrayList<String> man = new ArrayList<>();
7 ArrayList<String> woman = new ArrayList<>();
8
9 man.add("刘德华");
10 man.add("成龙");
11 man.add("周星驰");
12 man.add("周润发");
13 man.add("李小龙");
14 man.add("林正英");
15
16 woman.add("林青霞");
17 woman.add("关之琳");
18 woman.add("朱茵");
19 woman.add("林志玲");
20 woman.add("林心如");
21 woman.add("王祖贤");
22
23 Stream.concat(man.stream().filter(s -> s.length() == 3).limit(3),woman.stream().filter(s -> s.startsWith("林")).skip(1)).map(Actor::new).forEach(s -> System.out.println(s.getName()));
24 }
25 }
2.4 Stream流的收集操作
概念
对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中。
常用方法
| 方法名 | 说明 |
| R collect(Collector collector) | 把结果收集到集合中 |
工具类Collectors提供了具体的收集方式
| 方法名 | 说明 |
| public static Collector toList() | 把元素收集到List集合中 |
| public static Collector toSet() | 把元素收集到Set集合中 |
| public static Collector toMap(Function keyMapper,Function valueMapper) | 把元素收集到Map集合中 |
1 import java.util.ArrayList;
2 import java.util.List;
3 import java.util.Map;
4 import java.util.Set;
5 import java.util.stream.Collectors;
6 import java.util.stream.Stream;
7
8 public class CollectorsDemo {
9 public static void main(String[] args) {
10 List<String> names = new ArrayList<>();
11 names.add("张无忌");
12 names.add("赵敏");
13 names.add("张三丰");
14 names.add("张果老");
15 names.add("张国立");
16 names.add("铁拐李");
17 names.add("张赫");
18 names.add("张飞");
19 Stream<String> nameStream = names.stream().filter(s -> s.length()==3);
20 List<String> threeWordsNames = nameStream.collect(Collectors.toList());
21 for (String s : threeWordsNames){
22 System.out.println(s);
23 }
24 System.out.println("------");
25 Stream<String> namesStreams = names.stream().filter(s ->s.startsWith("张"));
26 Set<String> threeNames = namesStreams.collect(Collectors.toSet());
27 for (String sm : threeNames){
28 System.out.println(sm);
29 }
30 System.out.println("------");
31 String[] strArray = {"1,张曼玉","2,林青霞","3,朱茵"};
32 Stream<String> strStream = Stream.of(strArray);
33 Map<String,String> bf = strStream.collect(Collectors.toMap(s -> s.split(",")[0],s -> s.split(",")[1]));
34 Set<String> keys = bf.keySet();
35 for (String key : keys){
36 String value = bf.get(key);
37 System.out.println(value);
38 }
39 }
40 }
JavaSE23-函数式接口&Stream流的更多相关文章
- 第46天学习打卡(四大函数式接口 Stream流式计算 ForkJoin 异步回调 JMM Volatile)
小结与扩展 池的最大的大小如何去设置! 了解:IO密集型,CPU密集型:(调优) //1.CPU密集型 几核就是几个线程 可以保持效率最高 //2.IO密集型判断你的程序中十分耗IO的线程,只要大于 ...
- 第十章 函数式接口&Stream流
10.1.函数式接口 10.1.1.概述 有且仅有一个抽象方法的接口,并且可以通过在类上标注@FunctionalInterface注解进行检测,建议自定义的函数式接口都加上这个注解 10.1.2.函 ...
- 13函数式编程&Stream流
13.1常用的函数式接口总结 接口名称 方法名称 抽象/默认 延迟/终结 方法描述 Supplier get 抽象 终结 供给型接口,无参有返回值,主要用于 Consumer accept 抽象 ...
- 函数式接口与Stream流
lambda表达式是jdk8的特性.lambda表达式的准则是:可推断,可省略. 常规代码写一个多线程 public class Main { public static void main(Stri ...
- Java的lamda表达式/函数式接口/流式计算
在我们看他人code的时候经常会看到,可能会经常看到lambda表达式,函数式接口,以及流式计算.在刚接触这些新功能时,也觉得真的有必要吗?但是现在写多了,发现这个功能确实能简化代码结构,提升编码效率 ...
- Java 8-Lambda表达式、方法引用、标准函数接口与流操作、管道操作之间的关系
1.Lambda表达式与接口之间的关系 只要Lambda表达式的声明形式与接口相一致,在很多情况下都可以替换接口.见如下代码 Thread t1 = new Thread(new Runnable() ...
- [一] java8 函数式编程入门 什么是函数式编程 函数接口概念 流和收集器基本概念
本文是针对于java8引入函数式编程概念以及stream流相关的一些简单介绍 什么是函数式编程? java程序员第一反应可能会理解成类的成员方法一类的东西 此处并不是这个含义,更接近是数学上的 ...
- JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用
jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default Lambda表达式 L ...
- 常用函数式接口与Stream API简单讲解
常用函数式接口与Stream API简单讲解 Stream简直不要太好使啊!!! 常用函数式接口 Supplier<T>,主要方法:T get(),这是一个生产者,可以提供一个T对象. C ...
随机推荐
- scrapy学习之爬虫练习平台22
前言 上一篇文章中爬取了爬虫练习平台的所有 ssr 网站,都是比较简单的,没有反爬措施,这次来爬一下后面的 spa 系列. 环境准备 这里沿用了上篇文章的环境和设置,就不重新搭建环境了. 开始爬取 s ...
- ISITDTU CTF 2020 部分Web题目Writeup
周末,跟着m3w师傅打ISITDTUCTF,m3w师傅带弟弟上分,Tql! Web1 给了源码: <?php class Read{ public $flag; public function ...
- ServerLess之云函数实践-天气API
关注我的个人博客,发掘更多的内容 ServerLess之云函数实践-天气API 前言 云计算是大势所趋 Serverless 架构即"⽆服务器"架构,它是一种全新的架构方式,是云计 ...
- VMware与Device/Credential Guard不兼容问题
启动虚拟机vmware突然报不兼容错误 解决方法: 1首先打开控制面板>程序>启动或关闭Windows功能, 取消Hyper-v的勾选 2.在往下划,关闭Windows沙盒的勾选沙盒和虚拟 ...
- [LGOJ1273]有线电视网
solution 用了一个很有意思的转移方法. $dp[i][j] $ 表达 \(i\) 作为根,\(j\)个终端时最大的收益,即钱数,当\(0\leq dp[1][i]\)时,即以1为根可以转移到\ ...
- CSS3 学习笔记(上)
一.CSS简介 CSS(Cascading Style Sheets)层叠样式表.其中,样式定义为如何显示HTML元素,它通常储存在样式表,将样式添加到HTML中,能够解决内容与表现分离的问题.由于网 ...
- 变更mysql的数据类型兼容小数测试
来吧 我也没想到有一天要做这个测试: 想分为这几步吧: 1.先看看mysql本身支不支持数据的变更 2.再看看mybatis能不能用int接受double和decimal 先看下mysql: alte ...
- SQL优化之SQL 进阶技巧(上)
由于工作需要,最近做了很多 BI 取数的工作,需要用到一些比较高级的 SQL 技巧,总结了一下工作中用到的一些比较骚的进阶技巧,特此记录一下,以方便自己查阅,主要目录如下: SQL 的书写规范 SQL ...
- redis雪崩,击穿,穿透
redis穿透 什么是redis穿透? 1.查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存 2.这将导致这个不存在的数据每次请求都要到存储层 ...
- 第15.46节、PyQt显示部件:OpenGL Widget部件功能简介及使用案例
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 OpenGL Widget部件是一个Op ...