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流的更多相关文章

  1. 第46天学习打卡(四大函数式接口 Stream流式计算 ForkJoin 异步回调 JMM Volatile)

    小结与扩展 池的最大的大小如何去设置! 了解:IO密集型,CPU密集型:(调优)  //1.CPU密集型 几核就是几个线程 可以保持效率最高 //2.IO密集型判断你的程序中十分耗IO的线程,只要大于 ...

  2. 第十章 函数式接口&Stream流

    10.1.函数式接口 10.1.1.概述 有且仅有一个抽象方法的接口,并且可以通过在类上标注@FunctionalInterface注解进行检测,建议自定义的函数式接口都加上这个注解 10.1.2.函 ...

  3. 13函数式编程&Stream流

    13.1常用的函数式接口总结   接口名称 方法名称 抽象/默认  延迟/终结 方法描述 Supplier get 抽象 终结 供给型接口,无参有返回值,主要用于 Consumer accept 抽象 ...

  4. 函数式接口与Stream流

    lambda表达式是jdk8的特性.lambda表达式的准则是:可推断,可省略. 常规代码写一个多线程 public class Main { public static void main(Stri ...

  5. Java的lamda表达式/函数式接口/流式计算

    在我们看他人code的时候经常会看到,可能会经常看到lambda表达式,函数式接口,以及流式计算.在刚接触这些新功能时,也觉得真的有必要吗?但是现在写多了,发现这个功能确实能简化代码结构,提升编码效率 ...

  6. Java 8-Lambda表达式、方法引用、标准函数接口与流操作、管道操作之间的关系

    1.Lambda表达式与接口之间的关系 只要Lambda表达式的声明形式与接口相一致,在很多情况下都可以替换接口.见如下代码 Thread t1 = new Thread(new Runnable() ...

  7. [一] java8 函数式编程入门 什么是函数式编程 函数接口概念 流和收集器基本概念

      本文是针对于java8引入函数式编程概念以及stream流相关的一些简单介绍 什么是函数式编程?   java程序员第一反应可能会理解成类的成员方法一类的东西 此处并不是这个含义,更接近是数学上的 ...

  8. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  9. 常用函数式接口与Stream API简单讲解

    常用函数式接口与Stream API简单讲解 Stream简直不要太好使啊!!! 常用函数式接口 Supplier<T>,主要方法:T get(),这是一个生产者,可以提供一个T对象. C ...

随机推荐

  1. MQ消息中间件,面试能问些什么?

    MQ消息中间件,面试能问些什么? 为什么使用消息队列?消息队列的优点和缺点? kafka.activemq.rabbitmq.rocketmq都有什么优缺点? 面试官角度分析: (1)你知不知道你们系 ...

  2. 推荐一个适用于SpringBoot项目的轻量级HTTP客户端框架,快来试试它!

    在SpringBoot项目直接使用okhttp.httpClient或者RestTemplate发起HTTP请求,既繁琐又不方便统一管理.因此,在这里推荐一个适用于SpringBoot项目的轻量级HT ...

  3. Guitar Pro 教程之有效的几种泛音

    学习音乐的朋友们都知道,泛音的种类分为好几种,一般分为自然泛音和人工泛音,击弦泛音,拨片泛音,半泛音等等.本章节采用图文结合的方式讲解{cms_selflink page='index' text=' ...

  4. 如何查看CDR文件是出自哪个版本?

    如何才能知道某个cdr文件用哪个版本的CorelDRAW软件打开?网上CorelDRAW软件有很多版本,都不知该下哪个了?这是我听到大家问道最多的问题,这是因为CDR低版本软件打不开高版本文件. 方法 ...

  5. 简单几步就能把素材变成大片?老司机推荐Vegas

    "素材编辑"一般分为两种,一种是对时间线素材长度和位置的编辑,另一种就是遮罩法操作. 第一种,裁剪素材(将素材在我们选定的位置一分为二),对时间线上的素材进行裁剪,有两种方法: 一 ...

  6. 「LOJ 6287」诗歌

    题面 LOJ 6287 Solution 枚举中间点\(j\),题目即求是否存在\(m\)使\(a[j]-m\)与\(a[j]+m\)分别在\(j\)两侧. 对于\(j\)左侧任意一个点\(i\),都 ...

  7. 用大白话讲大数据HBase,老刘真的很用心(1)

    老刘今天复习HBase知识发现很多资料都没有把概念说清楚,有很多专业名词一笔带过没有解释.比如这个框架高性能.高可用,那什么是高性能高可用?怎么实现的高性能高可用?没说! 如果面试官听了你说的,会有什 ...

  8. Python生成随机测试数据

    前言 安装 pip install Faker 使用 from faker import Faker fake = Faker() name = fake.name() address = fake. ...

  9. 【mq读书笔记】mq消息发送

    钩子的注册: DefaultMQProducerImpl#registerSendMessageHook注册钩子处理类,可注册多个. public SendResult sendMessage( fi ...

  10. Vue.js 桌面端自定义滚动条组件|vue美化滚动条VScroll

    基于vue.js开发的小巧PC端自定义滚动条组件VScroll. 前段时间有给大家分享一个vue桌面端弹框组件,今天再分享最近开发的一个vue pc端自定义滚动条组件. vscroll 一款基于vue ...