list.parallelStream()操作线程不安全的数据集合时存在线程不安全的问题。
解决list.parallelStream()并行流线程安全的方式:
List<Integer> list4 = list1.parallelStream().collect(Collectors.toList());
或者直接使用线程安全的集合来保证线程安全 collect()/reduce()等线程安全的终断操作来保证线程安全问题
结论:
Stream并行安全的问题,在业务处理的过程中,主要通过自定义编码添加线程锁的方式,或者使用Stream api中提供的线程安全的终端操作来完成执行过程,但是在更多的场景中,如果我们遇到多线程问题会直接使用线程安全的集合来规范数据源。
jvm在内部生成一个静态方法,也生成了一个匿名内部类且实现了Lambda的目标类型接口,然后调用了一下生成的静态方法。
总结:
lambda表达式中变量操作优化了匿名内部类型中this关键字;
不在单独建立对象作用域,表达式本身就是所属类型对象的一部分,在语法语义上使用更加简洁。
JDK8中为什么要提供lambda表达式这种新技术的语法糖呢?
因为在项目开发中,我们经常会有代码质量控制这样的要求,让编写的代码更加趋于数据的有效处理,也就是编码即数据的开发模式,也就是Model Code as Data。
Model Code as Data尽可能轻量级的将代码封装为数据。这种操作模式在传统的编码中通过接口以及实现类的方式(或者匿名内部类的方式)完成功能的处理,但传统的这种模式下存在大量的问题。
- 语法冗余:在传统的编码中和数据处理无关的代码较多;
- this关键字:在匿名内部类处理方式中,this关键字在内部类型中,它的变量绑定以及变量访问存在很大的误区;
- 变量捕获:匿名内部类型中对于当前在内部类型的处理会有特殊的要求;
- 数据控制:并不是特别的友好。
函数式接口和Lambda表达式的关系
stream 操作集合数据下
stream操作集合获取stream方法
stream常用api
1
方法重载对lambda表达式的影响。也可以使用lambad /** * 方法重载对lambda表达式的影响 */ public class App4 { interface Param1 { void outInfo(String info); } interface Param2 { void outInfo(String info); } interface Param3 { void outInfo(String info, int index); } interface Param4 { void outInfo(String info, int index); } public void lambdaMethod_1(Param1 param) { param.outInfo("hello param1 imooc"); } public void lambdaMethod_1(Param2 param) { param.outInfo("hello param1 imooc"); } public void lambdaMethod_2(Param1 param, int index) { param.outInfo("hello param1 imooc---" + index); } public void lambdaMethod_2(Param2 param, int index) { param.outInfo("hello param1 imooc---" + index); } public void lambdaMethod_3(Param3 param, int index) { param.outInfo("hello Param3 imooc", index); } public void lambdaMethod_3(Param4 param, int index) { param.outInfo("hello param4 imooc", index); } public static void main(String[] args) { App4 app = new App4(); app.lambdaMethod_1(new Param1() { @Override public void outInfo(String info) { System.out.println(info); } }); app.lambdaMethod_1(new Param2() { @Override public void outInfo(String info) { System.out.println(info); } }); app.lambdaMethod_2(new Param1() { @Override public void outInfo(String info) { System.out.println(info); } }, 1); app.lambdaMethod_2(new Param2() { @Override public void outInfo(String info) { System.out.println(info); } }, 2); app.lambdaMethod_3(new Param3() { @Override public void outInfo(String info, int index) { System.out.println(info + "#############" + index); } }, 3); app.lambdaMethod_3(new Param4() { @Override public void outInfo(String info, int index) { System.out.println(info + "#############" + index); } }, 4); System.out.println("--------------------------------------------------------------------------"); app.lambdaMethod_1((Param1) info -> { System.out.println(info); }); app.lambdaMethod_1((Param2) info -> { System.out.println(info); }); app.lambdaMethod_2((Param1) info -> { System.out.println(info); }, 3); app.lambdaMethod_2((Param2) info -> { System.out.println(info); }, 4); app.lambdaMethod_3((Param3) (info, index) -> { System.out.println(info + "#############" + index); },5); app.lambdaMethod_3((Param4) (info, index) -> { System.out.println(info + "#############" + index); },5); } }
无参数
jdk原生里面原来就有这么多很棒的封装,很厉害。
/**
* java.util.function 包提供了大量函数式接口
*
* 1. Predicate 接收参数T对象,返回boolean类型的结果
* 2. Consumer 接收参数T对象,没有返回值
* 3. Function 接收参数T对象,返回R对象
* 4. Supplier 不接收任何参数,直接通过get()获取指定值
* 5. UnaryOperator 接口参数T对象,执行业务处理后,返回更新后的T对象
* 6. BinaryOperator 接口接收两个T对象,执行业务处理后,返回T对象
*/
2
1
1
1
4
3
2
什么是Lambda
lambda表达式的基本语法
声明:就是和lambda表达式绑定的接口类型
参数:包含在一对圆括号中,和绑定的接口中的抽象方法中的参数个数及顺序一致
操作符;->
执行代码块:包含在一对大括号中,出现在操作符的右侧
[接口声明]=(参数)-> {执行代码块}
注:lambda表达式,必须和接口进行绑定
lambda表达式的参数,可以附带0个到n个参数,括号中的参数类型可以不用指定,jvm在运行时,会自动根据绑定的抽象方法中的参数进行推广
lambda表达式的返回值,如果代码只有一行,并且没有大括号,不用写return关键字,单行代码的执行结果,会自动返回,如果添加了大括号,或多行代码,必须通过return返回结果
//没有参数,没有返回值
interface ILambal{
void test();}
//有参数,没有返回值
interface ILambal{
void test(String name,int age);}
//有参数有返回值
interface ILambal{
int test(int x,int y);}
java.util.function提供大量的函数式接口
Predicate 接受参数T对象,返回一个boolean类型结果
Consumer 接受参数T对象,没有返回值
Function 接受参数T对象,返回R对象
Supplier 不接受任何参数,直接通过get获取指定类型的对象
UnaryOperator 接口参数T对象,执行业务处理后,返回更新后的T对象
BinaryOperator接口接受两个T对象,执行业务处理后,返回一个T对象
Stream常用api
Stream常用api
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
personList.add(new Person("kar","男",22));
personList.add(new Person("nioa","女",15));
personList.add(new Person("duola","男",32));
personList.add(new Person("miky","女",55));
personList.add(new Person("sisi","男",44));
personList.add(new Person("holy","女",42));
//原始方法
// Collections.sort(personList, new Comparator<Person>() {
// @Override
// public int compare(Person o1, Person o2) {
// return o1.getAge() - o2.getAge();
// }
// });
// System.out.println(personList);
//lambda方法
// Collections.sort(personList,(o1, o2) -> o1.getAge() - o2.getAge());
// System.out.println(personList);
//lambda静态方法使用
// Collections.sort(personList,Person::compareByAge);
// System.out.println(personList);
//lambda实例方法引用
Person person = new Person();
Collections.sort(personList,person::compareByAge2);
System.out.println(personList);
//构造方法引用
InitPerson initPerson = Person::new;
initPerson.initPerson("张三","男",123);
深入理解lambda表达式
方法重载和lambda表达式