当前位置: 首页 > news >正文

lambda表达式详解

 1、 lambda表达式


JVM内部是通过invokedynamic指令来实现Lambda表达式的
Lambda中允许将一个函数作为方法的参数,即函数作为参数传递进方法中
使用Lambda表达式可以使代码更加简洁

2、变量作用域

Lambda表达式只能引用标记了final的外层局部变量.即不能在Lambda表达式内部修改定义在作用域外的局部变量,否则会导致报错
Lambda表达式中可以直接访问外层的局部变量
Lambda表达式中外层局部变量可以不用声明为final, 但是必须不可被后面的代码修改,即隐性地具有final的语义
Lambda表达式中不允许声明一个与外层局部变量同名的参数或者局部变量

 

3、使用示例

匿名内部类
匿名内部类: 匿名内部类仍然是一个类,不需要指定类名,编译器会自动为该类取名
Java中的匿名内部类:

 

public class MainAnonymousClass {public static void main(String[] args) {new Thread(new Runnable(){@Overridepublic void run(){System.out.println("Anonymous Class Thread run()");}}).start();;}
}

使用Lambda表达式实现匿名内部类:

public class MainLambda {public static void main(String[] args) {new Thread(() -> System.out.println("Lambda Thread run()")).start();;}
}

4、带参函数

带参函数的简写:

List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, new Comparator<String>() { // 接口名@Overridepublic int compare(String s1, String s2) { // 方法名if(s1 == null)return -1;if(s2 == null)return 1;return s1.length() - s2.length();           }
});

上述代码通过内部类重载了Comparator接口的compare() 方法来实现比较逻辑. 采用Lambda表达式可简写如下:

List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, (s1, s2) -> { // 省略参数表类型if (s1 == null)return -1;if (s2 == null)return 1;return s1.length() - s2.length();
});

上述代码根内部类的作用一样
除了省略了接口名和方法名,代码中的参数类型也可以省略
因为javac的类型推断机制,编译器能够根据上下文信息推断出参数的类型

5、 Collection

5.1、forEach

增强型for循环:

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
for(String str : list) {if (str.length() > 3)System.out.println(str);
}

使用forEach() 方法结合匿名内部类实现:

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
list.forEach(new Consumer<String>(){@Overridepublic void accept(String str) {if (str.length() > 3) {System.out.println(str);}}
});

使用forEach()结合Lambda表达式迭代

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
list.forEach(str -> {if (str.length() > 3) {Systemm.out.println(str);}       
});

上述代码给forEach() 方法传入一个Lambda表达式,不需要知道accept() 方法,也不需要知道Consumer接口,类型推导已经完成了这些

5.2、removeIf

该方法签名: boolean removeIf(Predicate<? super E> filter);
删除容器中所有满足filter指定条件的元素
Predicate是一个函数接口,里面有一个待实现的方法boolean test(T t)
如果需要在迭代过程中对容器进行删除操作必须使用迭代器, 否则会抛出ConcurrentModificationException.
使用迭代器删除列表元素:

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {if (it.next().length > 3) {it.remove();}
}
ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
list.removeIf(new Predicate<String>(){@Overridepublic boolean test(String str) {return str.length() > 3;}
});

使用removeIf结合Lambda表达式实现:

Array<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
list.removeIf(str -> str.length() > 3);

使用Lambda表达式不需要记忆Predicate接口名,也不需要记忆test() 方法名,只需要此处需要一个返回布尔类型的Lambda表达式

5.3、replaceAll

该方法签名: void replaceAll(UnaryOperator<E> operator);
对每个元素执行operator指定的操作,并用操作结果来替换原来的元素
UnaryOperator是一个函数接口,里面有待实现的方法T apply(T t)
使用下标实现元素替换:

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
for (int i = 0; i < list.size(); i ++) {String str = list.get(i)if (str.length() > 3) {list.set(i, str.toUpperCase());}
}

使用replaceAll结合匿名内部类实现:

ArrayList<String> list =new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
list.replaceAll(new UnaryOperator<>(String){@Overridepublic String apply(String str) {if (str.length() > 3) {return str.toUpperCase();}return str;}
});

代码调用replaceAll() 方法,并使用匿名内部类实现UnaryOperator接口
使用Lambda表达式实现:

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
list.replaceAll(str -> {if (str.length > 3) {return str.toUpperCase();}return str;
});

 5.4、sort

该方法定义在List接口中,方法签名: void sort(Comparator<? super E> c);
根据c指定的比较规则对容器进行排序
Comparator接口中需要实现接口int compare(T o1, T o2)
使用Collections的sort() 方法:

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String str1, String str2) {return str1.length() - str2.length();}
});

直接使用List.sort() 方法,结合Lambda表达式:

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));
list.sort((str1, str2) -> str1.length() - str2.length());

5.5 、spliterator

该方法签名: Spliterator<E> spliterator();
Spliterator既可以像Iterator那样逐个迭代,也可以批量迭代,批量迭代可以降低迭代的开销
Spliterator是可拆分的,一个Spliterator可以通过调用Spliterator<T> trySplit() 方法来尝试分成两个.一个是this, 一个是新返回的元素.这两个迭代器代表的元素没有重叠
可通过多次调用Spliterator.trySplit() 方法来分解负载,以便于多线程处理

5.6、stream和parallStream

Stream() 和parallStream() 分别返回该容器的Stream视图表示
parallStream() 返回并行的Stream
Stream是Java函数式编程的核心类

6、 Map

6.1、forEach

该方法签名: void forEach(BiConsumer<? super K,? super V> action);
对Map中的每个映射执行action操作
BiConsumer是一个函数接口,里面有一个待实现方法 void accept(T t, U u);

使用Java 7之前的方式输出Map中所有的对应关系:

HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
for (Map.Entry<Integer, String> entry : map.entrySet()) {system.out.println(entry.getKey() + "=" + entry.getValue());
}

使用Map的forEach() 方法,结合匿名内部类:

HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.forEach(new BiConsumer<Integer, String>() {@Overridepublic void accept(Integer k, String v) {System.out.println(k + "=" + v);}
});

使用Lambda表达式:

HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.forEach((k, v) -> System.out.println(k + "=" + v));

6.2、getOrDefault

该方法签名: V getOrDefault(Object key, V defaultValue);
按照给定的key查询Map中对应的value, 如果没有找到则返回defaultValue
查询Map中指定键所对应的值,如果不存在则返回NoValue:
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
System.out.println(map.getOrDefault(4,"NoValue"));

 6.3、putIfAbsent

该方法签名: V putIfAbsent(K key, V value);
只有在不存在key值的映射或映射值为null时,才将value指定的值放入到Map中,否则不对Map做修改
该方法将判断和赋值合二为一,使用起来更加方便

6.4、remove

该方法签名: remove(Object key);
根据指定的key值删除Map中映射关系
该方法签名: remove(Object key, Object value);
只有在当前Map中key正好映射到value时才删除该映射

6.5、replace

该方法签名: replace(K key, V value);
只有在当前Map中key的映射存在时才用value去替换原来的值
该方法签名: replace(K key, V oldValue, V newValue);
只有在当前Map中key的映射存在且等于oldValue时,才用newValue去替换原来的值,否则不做任何操作

6.5、replaceAll

该方法签名: replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
对Map中的每个映射执行function操作,并用function的执行结果替换原来的value
其中BiFunction是一个函数接口,里面有一个待实现的方法R apply(T t, U u)
使用Java 7以前的方式将Map中的映射关系的单词都转换成大写:

HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
for (Map.Entry<Integer, String> entry : map.entrySet()) {entry.setValue(entry.getValue().toUpperCase());
}

使用replaceAll方法结合匿名内部类:

HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.replaceAll(new BiFunction<Integer, String, String>(){@Overridepublic String apply(Integer k, String v) {return v.toUpperCase();}
});

使用Lambda表达式实现:

HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.replaceAll(<k, v> -> v.toUpperCase());

6.6、merge

>该方法签名: merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction);
如果Map中的key对应的映射不存在或者为null, 则将value, value不可能为null关联到key上
否则执行remappingFunction, 如果执行结果非null, 则用该结果与key关联,否则在Map中删除key的映射
其中BiFunction是一个函数接口,里面有一个待实现方法R apply(T t, U u)
merge()方法语义复杂,但使用的方式明确,经典的使用场景: 将新的错误信息拼接到原来的信息上:


http://www.mrgr.cn/news/34887.html

相关文章:

  • caozha-CEPCS(新冠肺炎疫情防控系统)
  • React Native 全栈开发实战班 :数据管理与状态之React Hooks 基础
  • Kafka基础知识学习
  • 内网对抗-信息收集篇SPN扫描DC定位角色区域定性服务探针安全防护凭据获取
  • 刷算法题(C++)
  • synchronized锁失灵?
  • AI赋能千人千面营销:从数据采集到精准用户画像的全流程解析
  • 亚马逊云科技的成功秘诀:韧性与持续创新的经验之道
  • .NET 一款新的内网对抗综合利用工具
  • 循环遍历把多维数组中的某个值改成需要的值
  • wpf如何进行数据绑定与动态数据操作?
  • 【电商搜索】现代工业级电商搜索技术-Ha3搜索引擎平台简介
  • 管理方法(11)-- 阿米巴经营
  • 深度学习之表示学习 - 贪心逐层无监督预训练篇
  • eBPF系列:开发流程
  • 数据科学的秘密武器:defaultdict——Python字典的自动化填充神器,让数据结构更灵活
  • python 实现word frequency functions词频函数算法
  • 卷积神经网络(CNN)图像处理与识别原理
  • 汽车HMI:UI设计进入了3D时代,设计师准备好了吗?
  • LabVIEW提高开发效率技巧----使用状态机架构
  • 低侧双向电流检测电路设计
  • GoJs 节点动态添加样式
  • AI驱动TDSQL-C Serverless 数据库技术实战营-Vanna配合ollama分析TDSQL-C Serverless 数据库
  • Mybatis基础操作
  • 奇迹再现!帕金森患者6年后停药,竟能自如行走:背后的故事与启示
  • 【Python】多个dataframe存入excel的不同的sheet表里,而不会被覆盖的方法