函数式接口与Stream流
lambda表达式是jdk8的特性.lambda表达式的准则是:可推断,可省略.
常规代码写一个多线程
public class Main {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("run ");
}
}).start();
}
}
lambda表达式写一个多线程
public class Main {
public static void main(String[] args) {
new Thread(() -> System.out.println("run")).start();
}
}
lambda表达式的使用限制是.只能用来代替一个接口的方法.
自定义一个带参数的接口方法
public interface Person {
public void show(String name);
}
public class Main {
public static void main(String[] args) {
personShow((String name) -> {
System.out.println(name);
}, "张三");
}
public static void personShow(Person p, String name) {
p.show(name);
}
}
lambda表达式语法分为两部分, 左边为参数,->右边为方法体.方法参数可以不指定类型,方法体如果只有一句可以省略大括号,省略return关键字.因为类型推断的原因,原则是能省就剩.
关于lambda表达式jdk8产生了一个新的注解@FunctionalInterface被这个注解修饰的接口,只能有一个抽象方法.称之为函数式接口.属于一个标记性接口,但是他对接口本身又有抽象方法个数的限制
JDK8内置的4个常用函数式接口
Consumer<T>:消费型接口 void accpet(T t);
public class Test1 {
public static void main(String[] args) {
Test1 test1 = new Test1();
test1.happy(1000,(m)-> System.out.println("您当前消费"+m+"元"));
}
public void happy(double money, Consumer<Double> con) {
con.accept(money);
}
}
Supplier<T>:供给型接口 T get();
public class Test1 {
public static void main(String[] args) {
Test1 test1 = new Test1();
List list = test1.getNumList(5, () -> {
return 1;
});
System.out.println(list.size());
}
public List<Integer> getNumList(int num, Supplier<Integer> sup) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
list.add(sup.get());
}
return list;
}
}
Fucntion<T,R>:函数型接口 R apply(T t);
public class Test1 {
public static void main(String[] args) {
Test1 test1 = new Test1();
String hehe = test1.strHandler("hehe", (s) -> s.toUpperCase());
System.out.println(hehe);
}
public String strHandler(String str, Function <String,String> f){
return f.apply(str);
}
}
Predicate<T>:断言型接口 boolean test(T t);
public class Test1 {
public static void main(String[] args) {
Test1 test1 = new Test1();
boolean b = test1.is(1, (s) -> s > 3);
System.out.println(b);
}
public boolean is(int n, Predicate<Integer> p) {
return p.test(n);
}
}
像这类的函数式接口定义的原因只是为了在我们需要自定义函数式接口时,可以使用定义好的函数式接口.
Stream流
先把源数据(集合只能是Collection集合,数组)变成流,然后对流中的数据进行操作,然后产生一个新的流.不会改变源数据.
public class Employee {
private String name;
private Integer age;
private Double pay;
public Employee(String name, Integer age, Double pay) {
this.name = name;
this.age = age;
this.pay = pay;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getPay() {
return pay;
}
public void setPay(Double pay) {
this.pay = pay;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", pay=" + pay +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return Objects.equals(name, employee.name) &&
Objects.equals(age, employee.age) &&
Objects.equals(pay, employee.pay);
}
@Override
public int hashCode() {
return Objects.hash(name, age, pay);
}
}
public class Test {
public static void main(String[] args) {
//集合获取流
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
Stream<String> stringStream = list.parallelStream();
//数组获取流,Stream IntStream LongStream 都继承自BaseStream
Stream<String> stream1 = Arrays.stream(new String[10]);
IntStream stream2 = Arrays.stream(new int[10]);
LongStream stream3 = Arrays.stream(new long[10]);
}
}
筛选与切片
filter--接收lambda,从流中排除某些元素
public class Test2 {
public static void main(String[] args) {
//创建源数据
List<Employee> employees = Arrays.asList(
new Employee("张十八", 18, 9999.99),
new Employee("张五十八", 58, 5555.55),
new Employee("张二十六", 26, 3333.33),
new Employee("张三十六", 36, 6666.66),
new Employee("张十二", 12, 8888.88));
//转换成流,对流中的数据进行过滤操作
Stream<Employee> employeeStream = employees.stream()
.filter((e) -> e.getAge() > 18);
//终止操作
//注意终止操作不可做两次,本身意义就像是,一个桶里装满了水,当我们终止操作相当于将水倒了出来,是不能进行重复操作的.
employeeStream.forEach((x)-> System.out.println(x));
}
}
Employee{name='张五十八', age=58, pay=5555.55}
Employee{name='张二十六', age=26, pay=3333.33}
Employee{name='张三十六', age=36, pay=6666.66}
limit--截断流,使其元素不超过给定数量
public class Test2 {
public static void main(String[] args) {
//创建源数据
List<Employee> employees = Arrays.asList(
new Employee("张十八", 18, 9999.99),
new Employee("张五十八", 58, 5555.55),
new Employee("张二十六", 26, 3333.33),
new Employee("张三十六", 36, 6666.66),
new Employee("张十二", 12, 8888.88));
//转换成流,对流中的数据进行过滤操作
Stream<Employee> employeeStream = employees.stream()
.limit(2);
//终止操作
employeeStream.forEach((x)-> System.out.println(x));
}
}
Employee{name='张十八', age=18, pay=9999.99}
Employee{name='张五十八', age=58, pay=5555.55}
skip(n)--跳过元素,返回一个扔掉了前n个元素的流,若流中的元素不足n个,则返回一个空流,与limit(n)互补
public class Test2 {
public static void main(String[] args) {
//创建源数据
List<Employee> employees = Arrays.asList(
new Employee("张十八", 18, 9999.99),
new Employee("张五十八", 58, 5555.55),
new Employee("张二十六", 26, 3333.33),
new Employee("张三十六", 36, 6666.66),
new Employee("张十二", 12, 8888.88));
//转换成流,对流中的数据进行过滤操作
Stream<Employee> employeeStream = employees.stream()
.skip(2);
//终止操作
employeeStream.forEach((x)-> System.out.println(x));
}
}
Employee{name='张二十六', age=26, pay=3333.33}
Employee{name='张三十六', age=36, pay=6666.66}
Employee{name='张十二', age=12, pay=8888.88}
distinct--筛选,通过流所产生的hashCode()和equals()去除重复元素
public class Test2 {
public static void main(String[] args) {
//创建源数据
List<Employee> employees = Arrays.asList(
new Employee("张十八", 18, 9999.99),
new Employee("张十八", 18, 9999.99),
new Employee("张十八", 18, 9999.99),
new Employee("张五十八", 58, 5555.55),
new Employee("张二十六", 26, 3333.33),
new Employee("张三十六", 36, 6666.66),
new Employee("张十二", 12, 8888.88));
//转换成流,对流中的数据进行过滤操作
Stream<Employee> employeeStream = employees.stream()
.distinct();
//终止操作
employeeStream.forEach((x)-> System.out.println(x));
}
}
Employee{name='张十八', age=18, pay=9999.99}
Employee{name='张五十八', age=58, pay=5555.55}
Employee{name='张二十六', age=26, pay=3333.33}
Employee{name='张三十六', age=36, pay=6666.66}
Employee{name='张十二', age=12, pay=8888.88}
映射
map--接收lambda,对流中的每一个记录都进行操作,然后将操作的返回值,从新读取到一个新的流中,注意这个map是有返回值的.我之所以会写上return 和{} 就是为了显示map产生的新流只是返回值的结果集合
public class Test3 {
public static void main(String[] args) {
//创建源数据
List<Employee> employees = Arrays.asList(
new Employee("张十八", 18, 9999.99),
new Employee("张五十八", 58, 5555.55),
new Employee("张二十六", 26, 3333.33),
new Employee("张三十六", 36, 6666.66),
new Employee("张十二", 12, 8888.88));
employees.stream()
.map((e) -> {
return e.getPay().intValue();
})
.forEach((e) -> System.out.println(e));
}
}
flatMap--接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流都连接成一个流
public class Test3 {
public static void main(String[] args) {
List<String> arrayList = Arrays.asList("a", "b", "c", "d");
//当一个流的元素还是流
Stream<Stream<Character>> streamStream = arrayList.stream().map((e) -> filterCharacter(e));
//双重forEach
streamStream.forEach((e) -> {
e.forEach((i) -> System.out.println(i));
});
System.out.println("-----------------------------");
//使用flatMap可以将多个流直接转换成一个流
Stream<Character> characterStream = arrayList.stream().flatMap((e) -> filterCharacter(e));
characterStream.forEach((e) -> {
System.out.println(e);
});
}
public static Stream<Character> filterCharacter(String str) {
List<Character> list = new ArrayList<>();
for (Character ch : str.toCharArray()) {
list.add(ch);
}
return list.stream();
}
}
a
b
c
d
-----------------------------
a
b
c
d
排序
sorted()自然排序
public class Test4 {
public static void main(String[] args) {
List<String> arrayList = Arrays.asList("b","a","c");
arrayList.stream()
.sorted()
.forEach((e)-> System.out.println(e));
}
}
a
b
c
sorted(Comparator com)定制排序
public class Test4 {
public static void main(String[] args) {
//创建源数据
List<Employee> employees = Arrays.asList(
new Employee("张十八", 18, 9999.99),
new Employee("张五十八", 58, 5555.55),
new Employee("张二十六", 26, 3333.33),
new Employee("张三十六", 36, 6666.66),
new Employee("张十二", 12, 8888.88));
employees.stream()
.sorted((e1, e2) -> {
return e1.getPay().compareTo(e2.getPay());
})
.forEach((e) -> System.out.println(e));
}
}
Employee{name='张二十六', age=26, pay=3333.33}
Employee{name='张五十八', age=58, pay=5555.55}
Employee{name='张三十六', age=36, pay=6666.66}
Employee{name='张十二', age=12, pay=8888.88}
Employee{name='张十八', age=18, pay=9999.99}
我们对stream流中的数据进行操作,最终都有一个停止操作.与其说是停止操作,不如说是你要这个流最终干什么.我们也看到了,不管我们做切割,筛选等操作,最终返回的还是一个stream流,所以我们将stream流最终
变成我们需要的数据就是终止操作,以上我们用的forEach就是停止操作,尽管他没有返回值
查找与匹配
allMatch--检查是否匹配所有元素
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
boolean b = list.stream()
.allMatch((e) -> e == 1);
System.out.println(b);//false
}
}
anyMatch--检查是否至少匹配一个元素
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
boolean b = list.stream()
.anyMatch((e) -> e == 1);
System.out.println(b);//true
}
}
noneMatch--检查是否没有匹配所有元素
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
boolean b = list.stream()
.noneMatch((e) -> e == 1);
System.out.println(b);//false
}
}
findFirst--返回当前流中的第一个元素
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
Optional<Integer> first = list.stream()
.findFirst();
//注意,此时返回的是一个Optional,这个是JDK8为了避免null而封装的一个对象
System.out.println(first.get());//1
}
}
findAny--返回流中的任意元素
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
//其实就是随机返回了一个,但是为了演示明显这里使用了串行流,也就是多线程.
Optional<Integer> first = list.parallelStream()
.findAny();
System.out.println(first.get());//
}
}
count--返回流中的总个数
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
long count = list.parallelStream()
.count();
System.out.println(count);//
}
}
max--返回流中的最大值
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
Optional<Integer> max = list.parallelStream()
.max((x, y) -> Integer.compare(x, y));
System.out.println(max.get());//
}
}
min--返回流中的最小值
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
Optional<Integer> max = list.parallelStream()
.min((x, y) -> Integer.compare(x, y));
System.out.println(max.get());//
}
}
收集元素,将流中的数据转换成集合
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3,4,5,6);
List<Integer> collect = list.stream()
.limit(2)
.collect(Collectors.toList());
System.out.println(collect.size());
}
}
public class Test5 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3,4,5,6);
LinkedHashSet<Integer> collect = list.stream()
.limit(2)
.collect(Collectors.toCollection(LinkedHashSet::new));
System.out.println(collect.size());
}
}
函数式接口与Stream流的更多相关文章
- 黑马函数式接口学习 Stream流 函数式接口 Lambda表达式 方法引用
- 常用函数式接口与Stream API简单讲解
常用函数式接口与Stream API简单讲解 Stream简直不要太好使啊!!! 常用函数式接口 Supplier<T>,主要方法:T get(),这是一个生产者,可以提供一个T对象. C ...
- Atiti 重定向标准输出到字符串转接口adapter stream流体系 以及 重定向到字符串
Atiti 重定向标准输出到字符串转接口adapter stream流体系 以及 重定向到字符串 原理::syso 向ByteArrayOutputStream这个流理想write字节..然后可以使 ...
- 8000字长文让你彻底了解 Java 8 的 Lambda、函数式接口、Stream 用法和原理
我是风筝,公众号「古时的风筝」.一个兼具深度与广度的程序员鼓励师,一个本打算写诗却写起了代码的田园码农! 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在 ...
- 第46天学习打卡(四大函数式接口 Stream流式计算 ForkJoin 异步回调 JMM Volatile)
小结与扩展 池的最大的大小如何去设置! 了解:IO密集型,CPU密集型:(调优) //1.CPU密集型 几核就是几个线程 可以保持效率最高 //2.IO密集型判断你的程序中十分耗IO的线程,只要大于 ...
- Java8新特性_lambda表达式和函数式接口最详细的介绍
Lambda表达式 在说Lambda表达式之前我们了解一下函数式编程思想,在数学中,函数就是有输入量.输出量的一套计算方案,也就是“拿什么东西做什么事情”. 相对而言,面向对象过分强调“必须通过对象的 ...
- JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用
jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default Lambda表达式 L ...
- Java的lamda表达式/函数式接口/流式计算
在我们看他人code的时候经常会看到,可能会经常看到lambda表达式,函数式接口,以及流式计算.在刚接触这些新功能时,也觉得真的有必要吗?但是现在写多了,发现这个功能确实能简化代码结构,提升编码效率 ...
- Java Stream 函数式接口外部实例的引用
Java Function Interface 函数式接口: Stream.empty() .filter(Predicate) .map(Function) .forEach(Consumer); ...
随机推荐
- 节点List相关操作
为方便遍历子节点,lxml将节点list的操作尽可能的与python处理list的方式一样保持一致 创建XML from lxml import etree root = etree.Element( ...
- 基于python的selenium常用操作方法(1)
1 selenium定位方法 Selenium提供了8种定位方式. · id · name · class name · tag ...
- 教妹学 Java:难以驾驭的多线程
00.故事的起源 “二哥,上一篇<集合>的反响效果怎么样啊?”三妹对她提议的<教妹学 Java>专栏很关心. “这篇文章的浏览量要比第一篇<泛型>好得多.” “这是 ...
- 使用ZeroClipboard操作剪切板
一.ZeroClipboard下载地址 点击下载 二.添加js引用 <script src="../Assets/js/jquery-1.8.3.min.js">< ...
- Web前端基础(7):JavaScript(一)
1. JavaScript概述 1.1 JavaScript历史背景介绍 布兰登 • 艾奇(Brendan Eich,1961年-),1995年在网景公司,发明的JavaScript. 一开始Java ...
- Python【day 13】内置函数02
一.作用域相关-2个 1.locals() 参数是空 返回当前位置作用域的所有变量,返回的是字典 当前位置:函数内,返回局部变量 当前位置:函数外,返回全局变量 2.globals() 参数是空 返回 ...
- paypal开发指南
一.开发者地址: https://developer.paypal.com 使用在paypal上注册的账号登陆即可, 二.沙箱账号 paypay自动会为你创建两个沙箱账号,一个商家,一个买家.在acc ...
- python 通过使用pandas的实现的Excel的批量转换CSV文件的处理
---恢复内容开始--- 最近同事在处理文件导入的时候需要把一批文件换成CSV的格式,但是直觉修改后缀是不生效的,而且xlsx和xls的文件没法直接换成CVS的文件,所以找了一下方式,并且自己实现了p ...
- 01初识 JavaScript
1.初识 JavaScript 1.1 JavaScript 是什么 l JavaScript 是世界上最流行的语言之一,是一种运行在客户端的脚本语言 (Script 是脚本的意思) l 脚本语言 ...
- Dynamics 365中计算字段与Now进行计算实体导入报错:You can't use Now(), which is of type DateTime, with the current function.
微软动态CRM专家罗勇 ,回复338或者20190521可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me. 计算字段是从Dynamics CRM 2015 SP1版本开始推 ...