对Lambda的一些感悟--类库

类库

随着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实例然后依次遍历)的职责;内部迭代只负责做什么,而怎么做留给类库处理。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容