函数式接口与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); ...
随机推荐
- 世界GDP数据可视化
各国GDP数据可视化 数据来自世界银行 导入资源包,如下: Pandas, numpy, seaborn 和 matplotlib import pandas as pd import numpy a ...
- Kubernetes之Pod使用
一.什么是Podkubernetes中的一切都可以理解为是一种资源对象,pod,rc,service,都可以理解是 一种资源对象.pod的组成示意图如下,由一个叫”pause“的根容器,加上一个或多个 ...
- GNSS频率分配表
说明: 公开资料表示,GPS L3用于核爆炸等高能红外辐射事件的侦查,L4用于电离层研究. GLONASS FDMA信号G1.G2.G3三个频段各自频点见以下附表,摘自ITU的频率协调结果. GLON ...
- 黄聪:php一句代码让http跳转https
//其他框架请加到入口某共公加载的文件中 //方法一 https状态 if(!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off'){ Head ...
- CENTOS 7 内网网段在用IP地址检测Shell脚本优化版
脚本内容 #!/bin/bash ############################################################################# # 用途: ...
- C# WinForm实现禁止最大化、最小化、双击标题栏、双击图标等操作
protected override void WndProc(ref Message m) { if (m.Msg==0x112) { switch ((int) m.WParam) { //禁止双 ...
- c#图片相关常用的方法及处理
总结一下图片相关,常用的几个操作 一 创建Image对象 1. 手头上有一些图片文件,希望转换成 c# 中 Image对象,然后加以使用. public static System.Drawing ...
- 深入理解JVM,类加载器
虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流(即字节码)”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称 ...
- l浏览器执行JS
浏览器执行JS 浏览器分成两部分:渲染引擎和JS引擎 渲染引擎:用来解析HTML与CSS,俗称内核,比如chrome浏览器的blink,老版本的webkit JS引擎:俗称JS解析器.用来读取网页中的 ...
- Sublime设置格式化代码快捷键ctrl+shift+r
1.以管理员身份运行sublime 2.首选项---按键绑定-用户,将以下代码复制即可(这里注意不要忘记在最后一行添加逗号哦) { "keys": ["ctrl+shif ...