美文网首页文字欲
对Lambda的一些感悟--类库

对Lambda的一些感悟--类库

作者: 绍圣 | 来源:发表于2019-04-04 18:18 被阅读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实例然后依次遍历)的职责;内部迭代只负责做什么,而怎么做留给类库处理。

    相关文章

      网友评论

        本文标题:对Lambda的一些感悟--类库

        本文链接:https://www.haomeiwen.com/subject/mnsxuqtx.html