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 ...
随机推荐
- MQ消息中间件,面试能问些什么?
MQ消息中间件,面试能问些什么? 为什么使用消息队列?消息队列的优点和缺点? kafka.activemq.rabbitmq.rocketmq都有什么优缺点? 面试官角度分析: (1)你知不知道你们系 ...
- 推荐一个适用于SpringBoot项目的轻量级HTTP客户端框架,快来试试它!
在SpringBoot项目直接使用okhttp.httpClient或者RestTemplate发起HTTP请求,既繁琐又不方便统一管理.因此,在这里推荐一个适用于SpringBoot项目的轻量级HT ...
- Guitar Pro 教程之有效的几种泛音
学习音乐的朋友们都知道,泛音的种类分为好几种,一般分为自然泛音和人工泛音,击弦泛音,拨片泛音,半泛音等等.本章节采用图文结合的方式讲解{cms_selflink page='index' text=' ...
- 如何查看CDR文件是出自哪个版本?
如何才能知道某个cdr文件用哪个版本的CorelDRAW软件打开?网上CorelDRAW软件有很多版本,都不知该下哪个了?这是我听到大家问道最多的问题,这是因为CDR低版本软件打不开高版本文件. 方法 ...
- 简单几步就能把素材变成大片?老司机推荐Vegas
"素材编辑"一般分为两种,一种是对时间线素材长度和位置的编辑,另一种就是遮罩法操作. 第一种,裁剪素材(将素材在我们选定的位置一分为二),对时间线上的素材进行裁剪,有两种方法: 一 ...
- 「LOJ 6287」诗歌
题面 LOJ 6287 Solution 枚举中间点\(j\),题目即求是否存在\(m\)使\(a[j]-m\)与\(a[j]+m\)分别在\(j\)两侧. 对于\(j\)左侧任意一个点\(i\),都 ...
- 用大白话讲大数据HBase,老刘真的很用心(1)
老刘今天复习HBase知识发现很多资料都没有把概念说清楚,有很多专业名词一笔带过没有解释.比如这个框架高性能.高可用,那什么是高性能高可用?怎么实现的高性能高可用?没说! 如果面试官听了你说的,会有什 ...
- Python生成随机测试数据
前言 安装 pip install Faker 使用 from faker import Faker fake = Faker() name = fake.name() address = fake. ...
- 【mq读书笔记】mq消息发送
钩子的注册: DefaultMQProducerImpl#registerSendMessageHook注册钩子处理类,可注册多个. public SendResult sendMessage( fi ...
- Vue.js 桌面端自定义滚动条组件|vue美化滚动条VScroll
基于vue.js开发的小巧PC端自定义滚动条组件VScroll. 前段时间有给大家分享一个vue桌面端弹框组件,今天再分享最近开发的一个vue pc端自定义滚动条组件. vscroll 一款基于vue ...