网站首页 > 技术文章 正文
构造器引用
构造器使用的前提是什么?
- 构造器参数列表要与接口中抽象方法的参数列表一致!
语法格式:
- 类名 :: new
数组引用
数组引用和构造引用基本相同
@Test public void test10(){ //传统Lambda实现 Function<Integer,int[]> function = (i) -> new int[i]; int[] apply = function.apply(10); System.out.println(apply.length); // 10 //数组类型引用实现 function = int[] ::new; apply = function.apply(100); System.out.println(apply.length); // 100 }
Collections中的常用函数接口
Java8新增了java.util.funcion包,里面包含常用的函数接口,这是Lambda表达式的基础,Java集合框架也新增部分接口,以便与Lambda表达式对接。
Java集合框架的接口继承结构:
Java集合框架的接口继承结构
上图中绿色标注的接口类,表示在Java8中加入了新的接口方法,当然由于继承关系,他们相应的子类也都会继承这些新方法。下表详细列举了这些方法。
这些新加入的方法大部分要用到java.util.function包下的接口,这意味着这些方法大部分都跟Lambda表达式相关。
Collection中的新方法
forEach()
该方法的签名为void forEach(Consumer action),作用是对容器中的每个元素执行action指定的动作,其中Consumer是个函数接口,里面只有一个待实现方法void accept(T t)。
匿名内部类实现:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 6, 9, 10)); list.forEach(new Consumer<Integer>(){ @Override public void accept(Integer integer){ if(integer % 3 == 0){ System.out.println(integer); } } });
lambda表达式实现:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 6, 9, 10)); list.forEach((s) -> { if (s % 3 == 0){ System.out.println(s); } });
removeIf()
该方法签名为boolean removeIf(Predicate filter),作用是删除容器中所有满足filter指定条件的元素,其中Predicate是一个函数接口,里面只有一个待实现方法boolean test(T t)。
匿名内部类实现:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 6, 9, 10)); list.removeIf(new Predicate<Integer>(){ // 删除长度大于3的元素 @Override public boolean test(Integer sum){ return sum % 3 == 0; } }); System.out.println(list);
lambda表达式实现:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 6, 9, 10)); list.removeIf(s -> s % 3 == 0); System.out.println(list);
replaceAll()
该方法签名为void replaceAll(UnaryOperator<E> operator),作用是对每个元素执行operator指定的操作,并用操作结果来替换原来的元素。其中UnaryOperator是一个函数接口,里面只有一个待实现函数T apply(T t)。
匿名内部类实现:
lambda表达式实现:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 6, 9, 10)); list.replaceAll(sum -> { if (sum % 3 == 0){ return ++sum; }else { return --sum; } }); System.out.println(list);
sort()
该方法定义在List接口中,方法签名为void sort(Comparator c),该方法根据c指定的比较规则对容器元素进行排序。Comparator接口我们并不陌生,其中有一个方法int compare(T o1, T o2)需要实现,显然该接口是个函数接口。
匿名内部类实现:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(6, 10, 9, 3)); Collections.sort(list, new Comparator<Integer>(){ @Override public int compare(Integer sum1, Integer sum2){ return sum1 - sum2; } }); System.out.println(list);
lambda表达式实现:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(6, 10, 9, 3)); System.out.println(list); list.sort((sum1, sum2) -> sum1 - sum2); System.out.println(list);
spliterator()
方法签名为Spliterator<E> spliterator(),该方法返回容器的可拆分迭代器。从名字来看该方法跟iterator()方法有点像,我们知道Iterator是用来迭代容器的,Spliterator也有类似作用,但二者有如下不同:
Spliterator既可以像Iterator那样逐个迭代,也可以批量迭代。批量迭代可以降低迭代的开销。
Spliterator是可拆分的,一个Spliterator可以通过调用Spliterator trySplit()方法来尝试分成两个。一个是this,另一个是新返回的那个,这两个迭代器代表的元素没有重叠。
可通过(多次)调用Spliterator.trySplit()方法来分解负载,以便多线程处理。
stream()和parallelStream()
stream()和parallelStream()分别返回该容器的Stream视图表示,不同之处在于parallelStream()返回并行的Stream。Stream是Java函数式编程的核心类,具体内容后面单独介绍。
Map中的新方法
forEach()
该方法签名为void forEach(BiConsumer action),作用是对Map中的每个映射执行action指定的操作,其中BiConsumer是一个函数接口,里面有一个待实现方法void accept(T t, U u)。
匿名内部类实现:
HashMap<Integer, String> map = new HashMap<>(); map.put(1, "我"); map.put(2, "拒绝"); map.put(3, "996"); map.forEach(new BiConsumer<Integer, String>(){ @Override public void accept(Integer key, String value){ System.out.println(key + "=" + value); } });
lambda表达式实现:
HashMap<Integer, String> map = new HashMap<>(); map.put(1, "我"); map.put(2, "拒绝"); map.put(3, "996"); map.forEach((key, value) -> System.out.println(key + "=" + value));
getOrDefault()
该方法跟Lambda表达式没关系,但是很有用。方法签名为V getOrDefault(Object key, V defaultValue),作用是按照给定的key查询Map中对应的value,如果没有找到则返回defaultValue。使用该方法可以省去查询指定键值是否存在的麻烦。
实现:
HashMap<Integer, String> map = new HashMap<>(); map.put(1, "我"); map.put(2, "拒绝"); map.put(3, "996"); // Java7以及之前做法 if(map.containsKey(4)){ System.out.println(map.get(4)); }else{ System.out.println("NoValue"); } // Java8使用Map.getOrDefault() System.out.println(map.getOrDefault(4, "NoValue"));
putIfAbsent()
该方法跟Lambda表达式没关系,但是很有用。方法签名为V putIfAbsent(K key, V value),作用是只有在不存在key值的映射或映射值为null时,才将value指定的值放入到Map中,否则不对Map做更改.该方法将条件判断和赋值合二为一,使用起来更加方便。
remove()
我们都知道Map中有一个remove(Object key)方法,来根据指定key值删除Map中的映射关系;Java8新增了remove(Object key, Object value)方法,只有在当前Map中key正好映射到value时才删除该映射,否则什么也不做。
replace()
在Java7及以前,要想替换Map中的映射关系可通过put(K key, V value)方法实现,该方法总是会用新值替换原来的值.为了更精确的控制替换行为,Java8在Map中加入了两个replace()方法,分别如下:
- replace(K key, V value),只有在当前Map中key的映射存在时才用value去替换原来的值,否则什么也不做。
- replace(K key, V oldValue, V newValue),只有在当前Map中key的映射存在且等于oldValue时才用newValue去替换原来的值,否则什么也不做。
replaceAll()
该方法签名为replaceAll(BiFunction function),作用是对Map中的每个映射执行function指定的操作,并用function的执行结果替换原来的value,其中BiFunction是一个函数接口,里面有一个待实现方法R apply(T t, U u)。
匿名内部类实现:
HashMap<Integer, String> map = new HashMap<>(); map.put(1, "我"); map.put(2, "拒绝"); map.put(3, "996"); map.replaceAll(new BiFunction<Integer, String, String>(){ @Override public String apply(Integer k, String v){ if (v.equals("我")){ v = "你"; } return v.toUpperCase(); } }); map.forEach((key, value) -> System.out.println(key + "=" + value));
lambda表达式实现:
HashMap<Integer, String> map = new HashMap<>(); map.put(1, "我"); map.put(2, "拒绝"); map.put(3, "996"); map.replaceAll((k, v) -> { if (v.equals("我")){ v = "你"; } return v.toUpperCase(); }); map.forEach((key, value) -> System.out.println(key + "=" + value));
merge()
该方法签名为merge(K key, V value, BiFunction remappingFunction)。
作用是:
- 如果Map中key对应的映射不存在或者为null,则将value(不能是null)关联到key上;
- 否则执行remappingFunction,如果执行结果非null则用该结果跟key关联,否则在Map中删除key的映射。参数中BiFunction函数接口前面已经介绍过,里面有一个待实现方法R apply(T t, U u)。
merge()方法虽然语义有些复杂,但该方法的用方式很明确,一个比较常见的场景是将新的错误信息拼接到原来的信息上,比如:
HashMap<Integer, String> map = new HashMap<>(); map.put(1, "我"); map.put(2, "拒绝"); map.put(3, "996"); map.forEach((key, value) -> System.out.println(key + "=" + value)); map.merge(1, "和你", (v1, v2) -> v1+v2); map.forEach((key, value) -> System.out.println(key + "=" + value));
compute()
该方法签名为compute(K key, BiFunction remappingFunction),作用是把remappingFunction的计算结果关联到key上,如果计算结果为null,则在Map中删除key的映射。
HashMap<Integer, String> map = new HashMap<>(); map.put(1, "我"); map.put(2, "拒绝"); map.put(3, "996"); map.forEach((key, value) -> System.out.println(key + "=" + value)); map.compute(1, (k,v) -> v == null ? "值为空" : v.concat("和你")); map.forEach((key, value) -> System.out.println(key + "=" + value));
computeIfAbsent()
该方法签名为V computeIfAbsent(K key, Function mappingFunction),作用是:只有在当前Map中不存在key值的映射或映射值为null时,才调用mappingFunction,并在mappingFunction执行结果非null时,将结果跟key关联。
Function是一个函数接口,里面有一个待实现方法R apply(T t)。
computeIfAbsent()常用来对Map的某个key值建立初始化映射.比如我们要实现一个多值映射,Map的定义可能是Map<K,Set<V>>,要向Map中放入新值,可通过如下代码实现:
实现:
Map<Integer, Set<String>> map = new HashMap<>(); // Java7及以前的实现方式 if(map.containsKey(1)){ map.get(1).add("123"); }else{ Set<String> valueSet = new HashSet<String>(); valueSet.add("123"); map.put(1, valueSet); } // Java8的实现方式 map.computeIfAbsent(1, v -> new HashSet<String>()).add("345"); map.forEach((key, value) -> System.out.println(key + "=" + value));
使用computeIfAbsent()将条件判断和添加操作合二为一,使代码更加简洁。
computeIfPresent()
该方法签名为V computeIfPresent(K key, BiFunction remappingFunction),作用跟computeIfAbsent()相反。即只有在当前Map中存在key值的映射且非null时,才调用remappingFunction,如果remappingFunction执行结果为null,则删除key的映射,否则使用该结果替换key原来的映射。
猜你喜欢
- 2024-11-16 3.1 Python高级编程-函数式编程工具
- 2024-11-16 面向对象编程的一些思考(面向对象编程的理解)
- 2024-11-16 知识总结-Java8 Stream函数式编程
- 2024-11-16 bind、call、apply 区别?如何实现一个bind?
- 2024-11-16 Javascript基础重拾笔记之手写apply、call
- 2024-11-16 java 8新特性 常用内置函数式接口
- 2024-11-16 7、JavaScript 内置的常用对象有哪些?该对象常用的方法(必会)
- 2024-11-16 Java中“::”是什么含义(java中+是什么)
- 2024-11-16 Java 8 中的 Function:让代码从繁琐到简洁的魔法工具
- 2024-11-16 13万字详细分析JDK中Stream的实现原理(中)
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-