Lambda表达式(第一点和第三点是重点):
1.匿名内部类可以简写为lambda表达式:省略new 和这个方法的定义,保留这个的方法体和参数)
2.注意:如果接口中的方法只有一个参数,则lambda表达式可以省略小括号
3.注意:如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号
此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
4.注意:Lambda表达式中可以省略参数的类型(下边都省略了参数的类型)
5.只要接口中只有一个抽象函数(抽象方法)就符合函数式接口(可以不用标注@FunctionalInterface)(就可以用此接口来写lambda表达式)
注意:只有一个抽象方法,但是接口包含其他default的非抽象方法也可以写成lambda格式。
Runable r=new Runable(){
public void run(){
System.out.println("我");
}
};
Thread t=new Thread®;
t.start();
注意:上边三部分代码可以简写成下边两部分:
Thread t=new Thread(new Runable(){
public void run(){
System.out.println("我");
}
});
t.start();
注意:因为Runnable是一个函数式接口(接口上标注有@FunctionalInterface注解<或者只有一个抽象方法的接口没标注此注解也可以>)
@FunctionalInterface
public interface Runnable{
public void run();
}
所以上边创建Runnable实现类的匿名内部类可以用lambda表达式书写
(省略new 和run方法的定义,保留run的方法体和参数)
Thread t=new Thread(() -> {
System.out.println("我");
});
t.start();
//如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号
//此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
//所以可以简写为下边格式:
Thread t=new Thread(() -> System.out.println(“我”) );
t.start();
//只要接口中只有一个函数就符合函数式接口(可以不用标注@FunctionalInterface)
@FunctionalInterface
interface I{
int y(int o);
}
class Test{
public static void main(String[] args) {
I i2=(o)->{return o;};
System.out.println( i2.y(4) );
//注意:如果接口中的方法只有一个参数,则lambda表达式可以省略小括号
I i3=o->{return o;};
System.out.println( i2.y(4) );
//注意:如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号
//此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
//所以上边代码可以省略成下边格式:
I i4=o-> o;
System.out.println( i2.y(4) );
}
}
再次练习:
class Test2{
private void test() {
//给Collections.sort()方法传入一个自定义比较器(一个匿名内部类对象)对ArrayList集合元素进行倒序排列
//compare方法返回负数1表示倒序排列元素
//(ArrayList是类似于数组的一种数据结构,叫做线性集合)
//注意这里的T表示数据类型(T表示任意类型,集合中存储ude是什么类型T就表示什么类型)
ArrayList list=new ArrayList<>();
list.add("aa"); list.add("bb"); list.add("cc");
Collections.sort(list,new Comparator(){
public int compare(T o1, T o2) {
return -1;
}
});
//把上边代码简写成匿名内部类的形式,结果如下
ArrayList list2=new ArrayList<>();
list2.add("aa"); list2.add("bb"); list2.add("cc");
Collections.sort(list2,(T o1, T o2) -> {
return -1;
});
//注意:如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号
//此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
ArrayList list3=new ArrayList<>();
list3.add("aa"); list3.add("bb"); list3.add("cc");
Collections.sort(list3,(T o1, T o2) -> -1);
}
}
三、Lambda表达式对集合进行遍历 集合.foreach(Consumer对象):
3.1.遍历List集合:
实际Lambda表达式对集合进行遍历和上边语法要求是一样的(都是讲匿名内部类简写成Lambda表达式)
public static void main(String[] args) {
//创建ArrayList集合并放入 3个整数
ArrayList list=new ArrayList<>();
list.add(80);list.add(93);list.add(78);
//遍历集合并打印每个元素*10后的结果
list.forEach(new Consumer() {
public void accept(Integer element) {
System.out.println(element*10);
}
});
//Consumer接口的accept方法只有一个抽象方法
//所以: 集合的foreach方法内传递的参数在99.9%的情况下都写成lambda表达式的格式
//创建ArrayList集合并放入 3个整数
ArrayList list2=new ArrayList<>();
list2.add(80);list2.add(93);list2.add(78);
//遍历集合并打印每个元素*10后的结果
list2.forEach((Integer element) ->{
System.out.println(element*10);
});
//创建ArrayList集合并放入 3个整数
ArrayList list3=new ArrayList<>();
list3.add(80);list3.add(93);list3.add(78);
//参数类型可以省略, 大括号可以省略, 可以改成下列格式(分号不能写):
list3.forEach(element -> System.out.println(element*10) );
//如果上边的输出语句换成if结构就需要加大括号
list3.forEach(element -> {
if(element*10>100){
System.out.println(element);
}
});
//注意: 集合.forEach()循环格式也经常写成 集合.stream().forEach() (这个不是重点)
//集合.forEach()表示调用集合的forEach()方法, 集合.stream().forEach() 表示
//调用Stream类的forEach()方法,效果相同
//上边if(element*10>100)表示在循环的过程中进行元素筛选,
//实际也可以先用 Stream的filter()方法 先筛选再循环操作元素, 具体如下(这个不是重点):
list3.stream().forEach(element -> {
if(element*10>100){
System.out.println(element);
}
});
Stream s=listx.stream().filter(new Predicate() {
public boolean test(Integer s) {
return s<20;
}
});
s.forEach(element -> System.out.println(element) );
3.2.lambda表达式中用::格式调用方法(这个不是重点)
public static void main(String[] args){
//如果只需要打印element的值(不是打印element*10),
// 可以将lambda表达式从element->System.out.println(element)改成
//System.out::println
list3.forEach(element -> System.out.println(element*10) );
//所以将上边代码可以改成下边格式:
list3.forEach(System.out::println);//表示调用System类中的
//public final static PrintStream out 变量的println非静态方法
//这种情况请参考下边案例再强化一遍(new ShowC()::showData):
}
3.3.list.forEach方法调用自定义循环处理器:
A.list.forEach方法调用自定义循环处理器:调用ShowC对象中的非静态方法showData()
public class TT {
public static void main(String[] args) {
ArrayList list=new ArrayList<>();
list.add(80);list.add(93);list.add(78);
list.forEach(new ShowC()::showData);
// 表示调用ShowC对象中的非静态方法showData()
}
}
class ShowC{
public void showData(Object obj){
System.out.println(obj.toString()+";");
}
}
B.list.forEach方法调用自定义循环处理器:调用ShowC对象中的静态方法showStaticData()
public class TT {
public static void main(String[] args) {
ArrayList list=new ArrayList<>();
list.add(80);list.add(93);list.add(78);
list.forEach(ShowC::showStaticData);
//这个地方调用showStaticData()方法的代码格式不一样
// 表示调用ShowC对象中的非静态方法showData()
}
}
class ShowC{
public static void showStaticData(Object obj){
System.out.println(obj.toString()+";");
}
}
3.4.遍历Map集合:
public static void main(String[] args) {
Map map = new HashMap() {{
put("a", "haha");
put("b", "hahaha");
put("d", "hahe");
put("c", "haheeee");
}};
map.forEach((k, v) -> {
System.out.print("key=" + k);
System.out.print("t");
System.out.println("value=" + v);
});
}
zhaoYQ(2022-05-07)
进程和线程的区别:如果西安比作操作系统
每个学校相当一一个进程,每个进程有自己的运行区域//切换进程开销大(电脑开启非常多个进程会很慢)//切换学校
学校里边有多个班级,每个班级相当于一个线程,所有班级共享同一个学校区域(共享进程的内存区域)//切换进程开销相对较小(电脑开启非常多个线程不会很慢)



