函数式接口与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); ...
随机推荐
- SpringBoot系列之profles配置多环境(篇二)
SpringBoot系列之profles配置多环境(篇二) 继续上篇博客SpringBoot系列之profles配置多环境(篇一)之后,继续写一篇博客进行补充 写Spring项目时,在测试环境是一套数 ...
- java war包 路径--解决war包中文件路径问题
https://blog.csdn.net/u013409283/article/details/51480948 转自:http://free-chenwei.iteye.com/blog/1507 ...
- 【踩坑系列】VS2019提示 ' the package could not be found in c\users\username\nuget\packages\. '
解决步骤 1.删除对应项目下的 obj 文件夹 2.重新生成该项目
- 这些好用却鲜为人知的Python库,你知道多少?
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 读芯术 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- Java日期时间API系列3-----Jdk7及以前的日期时间类的不方便使用问题
使用Java日期时间类,每个人都很熟悉每个项目中必不可少的工具类就是dateutil,包含各种日期计算,格式化等处理,而且常常会遇到找不到可用的处理方法,需要自己新增方法,处理过程很复杂. 1.Dat ...
- FCC---Create Visual Direction by Fading an Element from Left to Right---一个带好看背景色的圆形图案,从左到右移动,透明度opacity渐变为0.1,背景色渐渐消失的效果
For this challenge, you'll change the opacity of an animated element so it gradually fades as it rea ...
- iOS自定义TabBar使用popToRootViewControllerAnimated返回后tabbar重叠
解决方法 所以方法就是:遵循UINavigationController的代理,用代理方法解决该Bug,代码如下: 实现代理方法: { // 删除系统自带的tabBarButton for (UIVi ...
- Android应用打开外部文件
我们有时候遇到要打开一个文件,我们可以选择用其他应用打开,这时弹出来的应用列表,那么我们如何让自己开发的应用也能出现在里面呢? 第一步:设置启动Activity的intent-filter,给data ...
- Java垃圾收集器——Serial,Parallel,CMS,G1收集器概述
1.概述 Java应用启动的时候,除了配置Xms以及Xmx参数(Xmx:InitialHeapSize, Xms:MaxHeapSize),还需要选择合适的垃圾收集器. 截止Jdk1.8,共提供了7款 ...
- docker卷管理(四)
什么是数据卷 overlay2存储卷 docker镜像是由多个只读层叠加而成,启动容器时,docker会加载只读镜像层,并在镜像栈顶部添加一个可写层 如果运行中的容器修改了现有的一个已存在文件,那该文 ...