函数式接口与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); ...
随机推荐
- 《细说PHP》第四版 样章 第18章 数据库抽象层PDO 8-1
18.6.5 获取数据 PDO的数据获取方法与其他数据库扩展非常类似,只要成功执行SELECT查询,都会有结果集对象生成.不管使用PDO对象中的query()方法,还是使用prepare()和exe ...
- Knative 实战:一个微服务应用的部署
作者 | 元毅 阿里云智能事业群高级开发工程师 在 Istio 中提供了一个 Bookinfo 的示例,用于演示微服务之间的调用,那么如何在 Knative 中部署这个示例呢?本文将会给大家介绍一下在 ...
- 黄聪:mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高
mysql的SQL_CALC_FOUND_ROWS 使用 类似count(*) 使用性能更高 在很多分页的程序中都这样写: SELECT COUNT(*) from `table` WHERE ... ...
- Mysql优化之Explain查询计划查看
我们经常说到mysql优化,优化中一种常见的方式就是对于经常查询的字段创建索引.那么mysql中有哪些索引类型呢? 一.索引分类1.普通索引:即一个索引只包含单个列,一个表可以有多个单列索引 2.唯一 ...
- PHP中设计模式以及魔术方法
1.设计模式 1.1单例模式 口诀:三私一公 1.私有的静态属性用来保存对象的单例 2.私有的构造方法用来阻止在类的外部实例化 3.私有的__clone阻止在类的外部clo ...
- overflow-x:scroll失效问题解决
在移动设备上设置overflow-x:scroll,大部分机型都是展示正常的,在安卓哦5.0系统上,无论怎么样滚动条都不会生效,终于找到了解决办法: display: -webkit-box; // ...
- 利用Fiddler模拟通过Dynamics 365的OAuth 2 Client Credentials认证后调用Web API
微软动态CRM专家罗勇 ,回复337或者20190521可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me. 配置Dynamics 365 & PowerApps 支 ...
- 开关VoLTE流程分析(一)
开关按钮位置: 设置--> 更多--> 移动网络--> 增强型4G LTE模式 控件初始化addEnhanced4GLteSwitchPreference,该设置开关使用了Switc ...
- 仅用StoryBoard布局实现按钮的均匀分布
今天在做登录界面时设计的需求是,登录和取消按钮左右对称均匀分布,按钮大小不变如图 屏幕宽度变化时按钮宽度不变,三个间距相等并且随屏幕变化而变化,简单的说就是按钮均匀分布,在网上查了一些资料,弄得比较乱 ...
- python的几个实例程序员节日快乐
python的几个小实例 有参函数 def login(username, password): name = input("请输入您的姓名").strip() pwd = inp ...