文字欲

对Lambda的一些感悟--类库

2019-04-04  本文已影响4人  绍圣

类库

随着lambda表达式的标准正式启动后,使得JDK类库特别是Java集合的API进行大幅度的变化。新增了java.util.funcion包,此包中包含常用的函数接口,函数接口是Lambda表达式的基础。集合框架为了和Lambda表达式对接,也增加了接口。所以新增的API大部分都要用到java.util.funcion包下的接口,所以新增的方法和Lambda表达式有关。

Collection中新的方法

forEach()

void forEach(Consumer<? super E> action)

作用:对集合中的每个元素执行action指定的动作,Consumer是一个函数接口。

@FunctionalInterface

public interface Consumer<T> {

void accept(T t);

default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after);

return (T t) -> { accept(t); after.accept(t);};

}

}

示例:forEach和Lambda表达式结合使用

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

说明:在此方法中传入一个Lambda表达式,我们都不需要知道accept方法,也不需要知道有Consumer这么个接口。类型推导给我们做了这一切。

removeIf()

boolean removeIf(Predicate<? super E> filter)

作用:删除集合中所有满足filter指定条件的元素。Predicate是一个函数接口。

@FunctionalInterfacepublic interface Predicate<T> {

boolean test(T t);

default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); }

default Predicate<T> negate() { return (t) -> !test(t); }

default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); }

static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }

}

示例:removeIf和Lambda表达式结合使用

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));list.removeIf(str -> str.length()>3);// 删除长度大于3的元素

replaceAll()

void replaceAll(UnaryOperator<E> operator)

作用:对集合中的每个元素执行operator指定的操作,并用操作结果来替换原来的元素。UnaryOperator是一个接口函数

@FunctionalInterfacepublic interface UnaryOperator<T> extends Function<T, T> { static <T> UnaryOperator<T> identity() { return t -> t; }}

示例:replaceAll和Lambda表达式结合使用

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

sort()

void sort(Comparator<? super E> c)

作用:定义在List中,根据c指定的比较规则对集合元素进行排序。Comparator是一个函数接口。

示例:

ArrayList<String> list = new ArrayList<>(Arrays.asList("I", "love", "you", "too"));list.sort((str1, str2) -> str1.length()-str2.length()); // 按照字符串长度进行排序

spliterator()

Spliterator<E> spliterator()

作用:返回集合的可拆分迭代器,Spliterator是Iterator的增强版:1,Iterator逐个迭代,Spliterator既可以逐个迭代,又可以批量迭代。批量迭代的好处可以降低迭代的开销。2,Spliterator可拆分,一个Spliterator可以通过调用Spliterator<T> trySplit()方法来尝试分成两个。一个是this,另一个是新返回的那个,这两个迭代器代表的元素没有重叠。这样可以多次调用trySplit来分解集合,多线程来处理。

stream()和parallelStream()

stream()和parallelStream()分别返回该容器的Stream视图表示,parallelStream()返回并行的Stream。

Map中新的方法

forEach()

void forEach(BiConsumer<? super K,? super V> action)

作用:对map中每个映射执行action指定的操作,BiConsumer是一个函数接口。

@FunctionalInterfacepublic interface BiConsumer<T, U> { void accept(T t, U u); default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) { Objects.requireNonNull(after); return (l, r) -> { accept(l, r); after.accept(l, r); }; }}

getOrDefault()

V getOrDefault(Object key, V defaultValue)

作用:和Lambda表达式没什么关系。按照给定的key查询Map中对应的value。如果没有找到则发挥defaultValue。使用该方法可以省去查询指定键值是否存在的麻烦。

putIfAbsent()

V putIfAbsent(K key, V value)

作用:和Lambda表达式没什么关系。只有在不存在key值或映射值为Null时,才将value指定的值放到map中,否则不对map做更改。

remove()

作用:remove(Object key)方法,来根据指定key值删除Map中的映射关系。Java8中增加remove(Object key, Object value)方法,只有在当前Map中key正好映射到value时才删除该映射,否则什么也不做。

replace()

在Java8以前,想替换Map中的映射关系可通过put(K key, V value)方法实现,该方法总是会用新值替换原来的值。Java8在Map中加入了两个replace()方法。

1,replace(K key, V value):只有在当前Map中key的映射存在时才用value去替换原来的值,否则什么也不做。

2,replace(K key, V oldValue, V newValue),只有在当前Map中key的映射存在且等于oldValue时才用newValue去替换原来的值,否则什么也不做。

replaceAll()

replaceAll(BiFunction<? super K,? super V,? extends V> function)

作用:对map中的每个映射执行function指定操作,并用function的执行结果替换原来的value。BiFunction是一个函数接口。

@FunctionalInterfacepublic interface BiFunction<T, U, R> { R apply(T t, U u); default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t, U u) -> after.apply(apply(t, u)); }}

merge()

merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)

作用:1,如果Map中key对应的映射不存在或者为null,则将value(不能是null)关联到key上。2,否则执行remappingFunction,如果执行结果非null则用该结果跟key关联,否则在Map中删除key的映射。

compute()

compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)

作用:把remappingFunction的计算结果关联到key上,如果计算结果为null,则在Map中删除key的映射。

computeIfAbsent()

V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)

作用:只有在当前Map中不存在key值的映射或映射值为null时,才调用mappingFunction,并在mappingFunction执行结果非null时,将结果跟key关联。

Function函数接口

@FunctionalInterfacepublic interface Function<T, R> { R apply(T t); default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } static <T> Function<T, T> identity() { return t -> t; }}

computeIfPresent()

V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)

作用:只有在当前Map中存在key值的映射且非null时,才调用remappingFunction,如果remappingFunction执行结果为null,则删除key的映射,否则使用该结果替换key原来的映射。

内部迭代和外部迭代:集合类库主要依赖于外部迭代。Collection实现Iterable接口,使用户可以一次遍历集合的元素。

for (Shape shape : shapes) { shape.setColor(RED);}

上面的例子是外部迭代,for-each循环调用集合的iterator()方法进行依次遍历。外部迭代是串行的,并且必须按照集合中元素的顺序进行依次处理;集合框架无法对控制流进行优化(排序,并行)。

使用内部迭代代替外部迭代,用户把对迭代的控制权交给类库,并向类库传递迭代时所需的执行代码。

shapes.forEach(s -> s.setColor(RED));

用户把对操作的控制权交还给类库,类库就可以进行各种优化。

外部迭代同时承担了做什么(把形状设为红色)和怎么做(得到Iterator实例然后依次遍历)的职责;内部迭代只负责做什么,而怎么做留给类库处理。

上一篇 下一篇

猜你喜欢

热点阅读