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