Java8时Lambda表达式的出现,将行为作为参数传递进函数的函数式编程,大大简化了之前冗杂的写法。

如果你对Lambda还不了解,可以参考我之前的关于Lambda表达式的总结:Java8的Lambda表达式,你会不?

对于集合一类,我们来整理一下发生的变化叭。

Iterable的forEach

Iterable接口就是所有可迭代类型的父接口,我们熟知的Collection接口就是继承自它。Java8接口默认方法以及Lambda表达式的出现,让我们在遍历元素时对元素进行操作变得格外简单。

下面的forEach方法就是Java8新增的,它接受一个Consumer对象,是一个消费者类型的函数式接口。

    default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}

下面这段代码遍历输出每个元素。

    public void testForEach(){
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
list.forEach(System.out::println);
}

Iterator的forEachRemaining

java.util.Iterator是用于遍历集合的迭代器,接口定义如下:

public interface Iterator<E> {

    boolean hasNext();

    E next();

    default void remove() {
throw new UnsupportedOperationException("remove");
} default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}

default方法是Java8接口中新增的,forEachRemaining方法接收一个Consumer,我们可以通过该方法简化我们的遍历操作:

    /**
* Java8 为Iterator新增了 forEachRemaining(Consumer action) 方法
*/
public static void main(String[] args) { List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Iterator<Integer> iterator = list.iterator();
iterator.forEachRemaining(System.out::println);
}

Collection的removeIf

Java8为Collection增加了默认的removeIf方法,接收一个Predicate判断,test方法结果为true,就移除对应的元素。

    default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
// 判断元素是否需要被移除
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}

下面这段代码移除列表中的偶数元素。

    public void testRemoveIf() {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
list.removeIf(x -> x % 2 == 0);
list.forEach(System.out::println);
}

Stream操作

具体使用可以参照Java8的StreamAPI常用方法总结

    public void testStream(){
IntStream stream = IntStream.builder().add(1).add(2).add(3).build();
int max = stream.max().getAsInt();
System.out.println(max);
}

List的replaceAll

Java8为List接口增加了默认的replaceAll方法,需要UnaryOperator来替换所有集合元素,UnaryOperator是一个函数式接口。

    default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}

下面这个示例为每个元素加上3。

    public void testReplaceAll(){
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
list.replaceAll(x -> x + 3);
list.forEach(System.out::println);
}

List的sort

Java8为List接口增加了默认的sort方法,需要Comparator对象来控制元素排,我们可以传入Lambda表达式。

    default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}

下面这个例子将list逆序。

    public void testSort() {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
list.sort((x, y) -> y - x);
System.out.println(list);
}

Map的ForEach

Map接口在Java8同样也新增了用于遍历的方法:

    default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}

该方法接收一个二元的参数,分别对应key和value:

    private void print(Map<Integer,String> map){
map.forEach((x , y )-> {
System.out.println("x -> " + x + ", y -> " + y);
});
}

为了接下来测试方便,数据先准备一下:

    Map<Integer, String> map = new HashMap<>();

    {
map.put(1, "hello");
map.put(2, "summer");
map.put(3, "day");
map.put(4, "tqbx");
}

Map的remove

Java8新增了一个remove(Object key, Object value)方法。

    default boolean remove(Object key, Object value) {
// key存在且key对应的value确实是传入的value才移除
Object curValue = get(key);
if (!Objects.equals(curValue, value) ||
(curValue == null && !containsKey(key))) {
return false;
}
remove(key);
return true;
}

移除key为3且value为day的元素。

    @Test
public void testRemove(){
map.remove(3,"day");
print(map);
}

Map的compute相关方法

Object compute(Object key, BiFunction remappingFunction):该方法使用remappingFunction根据key-value对计算一个新value,情况如下:

  • 只要新value不为null,就使用新value覆盖原value。
  • 如果原value不为null,但新value为null,则删除原key-value对。
  • 如果原value、新value同时为null那么该方法不改变任何key-value对,直接返回null。

Object computeIfAbsent(Object key, Function mappingFunction)

  • 如果传给该方法的key参数在Map中对应的value为null,则使用mappingFunction根据key计算个新的结果。
  • 如果计算结果不为null,则用计算结果覆盖原有的value。
  • 如果原Map原来不包括该key,那么该方法可能会添加一组key-value对。

Object computeIfPresent(Object key, BiFunction remappingFunction)

  • 如果传给该方法的key参数Map中对应的value不为null,该方法将使用remappingFunction根据原key、value计算一个新的结果。
  • 如果计算结果不为null,则使用该结果覆盖原来的value。
  • 如果计算结果为null,则删除原key-value对。
    @Test
public void testCompute() {
//key==2 对应的value存在时,使用计算的结果作为新value
map.computeIfPresent(2, (k, v) -> v.toUpperCase());
print(map); //key==6 对应的value为null (或不存在)时,使用计算的结果作为新value
map.computeIfAbsent(6, (k) -> k + "haha");
print(map);
}

Map的getOrDefault

    default V getOrDefault(Object key, V defaultValue) {
V v;
// key存在或 value存在,则返回对应的value,否则返回defaultValue
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
    @Test
public void testGetOrDefault(){
// 获取指定key的value,如果该key不存在,则返回default
String value = map.getOrDefault(5, "如果没有key==5的value,就返回这条信息");
System.out.println(value);
}

Map的merge

    default V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
// 先获取原值
V oldValue = get(key);
// 原值为null,新值则为传入的value,不为null,则使用function计算,得到新值
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
// 新值如果为null,则移除原key-value对
if(newValue == null) {
remove(key);
} else {
// 不为null,则替换之
put(key, newValue);
}
// 返回新值
return newValue;
}
    @Test
public void testMerge(){
// key为2 的值 加上 +add
map.merge(2," + add",(oldval, newVal) -> oldval + newVal);
print(map);
}

Map的putIfAbsent

    default V putIfAbsent(K key, V value) {
// 得到原值
V v = get(key);
// 原值为null,则替换新值
if (v == null) {
v = put(key, value);
}
// 返回原值
return v;
}
    @Test
public void testPutIfAbsent(){
// key = 10 对应的value不存在, 则用101010 覆盖
String s1 = map.putIfAbsent(10, "101010");
System.out.println(s1);
print(map);
System.out.println("============================");
// key = 2 对应的value存在且为summer,返回summer
String s2 = map.putIfAbsent(2, "2222");
System.out.println(s2);
print(map);
}

输出结果

null
x -> 1, y -> hello
x -> 2, y -> summer
x -> 3, y -> day
x -> 4, y -> tqbx
x -> 10, y -> 101010
============================
summer
x -> 1, y -> hello
x -> 2, y -> summer
x -> 3, y -> day
x -> 4, y -> tqbx
x -> 10, y -> 101010

Map的replace相关方法

    @Test
public void testReplace(){
//boolean 将指定的 1 -> hello 键值对的value替换为hi
map.replace(1,"hello","hi");
print(map);
System.out.println("============================");
//V 指定key对应的value替换成新value
map.replace(2,"天乔巴夏");
print(map);
System.out.println("============================");
//void 对所有的key和value 进行计算,填入value中
map.replaceAll((k,v)-> k + "-" + v.toUpperCase());
print(map);
}

输出结果:

x -> 1, y -> hi
x -> 2, y -> summer
x -> 3, y -> day
x -> 4, y -> tqbx
============================
x -> 1, y -> hi
x -> 2, y -> 天乔巴夏
x -> 3, y -> day
x -> 4, y -> tqbx
============================
x -> 1, y -> 1-HI
x -> 2, y -> 2-天乔巴夏
x -> 3, y -> 3-DAY
x -> 4, y -> 4-TQBX

Java8新增的这些集合骚操作,你掌握了嘛?的更多相关文章

  1. <JAVA8新增内容>关于集合的操作(Collection/Iterator/Stream)

    因为下文频繁使用lambda表达式,关于Java中的lambda表达式内容请见: http://www.cnblogs.com/guguli/p/4394676.html 一.使用增强的Iterato ...

  2. java集合(3)-Java8新增的Stream操作集合

    Java8新增了Stream,IntStream,LongStream,DoubleStream等流式API,这些API代表多个支持串行和并行聚集操作的元素.上面的4个接口中,Stream是一个通用的 ...

  3. java集合(3)-Java8新增的Predicate操作集合

    Java8起为Collection集合新增了一个removeIf(Predicate filter)方法,该方法将批量删除符合filter条件的所有元素.该方法需要一个Predicate(谓词)对象作 ...

  4. Java8 新特性之集合操作Stream

    Java8 新特性之集合操作Stream Stream简介 Java 8引入了全新的Stream API.这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同 ...

  5. Java8 如何进行stream reduce,collection操作

    Java8 如何进行stream reduce,collection操作 2014-07-16 16:42 佚名 oschina 字号:T | T 在java8 JDK包含许多聚合操作(如平均值,总和 ...

  6. JAVA中的集合容器操作类

    目录 JAVA中的集合容器操作类 List集合 ArrayList的操作方法说明 LinkedList Stack Set Map Queue 总结 JAVA中的集合容器操作类 Java容器类库总共分 ...

  7. Java8增强的Map集合

    Map集合简介 Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,另外一组用于保存Map里的vlaue,key和value都可以是任何引用类型的数据. M ...

  8. 聊聊redis实际运用及骚操作

    前言 聊起 redis 咱们大部分后端猿应该都不陌生,或多或少都用过.甚至大部分前端猿都知道. 数据结构: string. hash. list. set (无序集合). setsorted(有序集合 ...

  9. 我天!xx.equals(null) 是什么骚操作??

    问题背景 我的天,最近做 Code Review 看到一个同事的骚操作,他写了一个工具类,大概是这样的: public static boolean isNull(Object object){ re ...

随机推荐

  1. Go 语言设计哲学之四:项目布局-你如何设计项目结构

    在多年的 Go 语言实践积累后逐渐形成了一种典型项目结构,如下图所示: 上面就是一个支持构建二进制可执行文件(在 src 下)的典型 Go 项目的结构. 1 src 目录: 存放项目要编译构建的可执行 ...

  2. 限流10万QPS、跨域、过滤器、令牌桶算法-网关Gateway内容都在这儿

    一.微服务网关Spring Cloud Gateway 1.1 导引 文中内容包含:微服务网关限流10万QPS.跨域.过滤器.令牌桶算法. 在构建微服务系统中,必不可少的技术就是网关了,从早期的Zuu ...

  3. 2020年SpringCloud 必知的18道面试题

    今天跟大家分享下SpringCloud常见面试题的知识. 1.什么是Spring Cloud? Spring cloud流应用程序启动器是基于Spring Boot的Spring集成应用程序,提供与外 ...

  4. 图创图书管理SQL注入漏洞

    payload root@kali:~# sqlmap -u http://2*0.*6.***.3:8080/opac/recommend/recommendBookList/list --data ...

  5. PHP核心配置基础解读

    PHP核心配置 原为引用 <代码审计企业级web代码安全架构>尹毅  第一章内容 Register_globals(全局变量开关) 会直接把用户GET.POST等方式提交上来的参数注册成为 ...

  6. wireshark分析nmap和metasploit内置的syn扫描

    syn扫描 syn扫描,根据三次握手,向端口发送syn包,如果对方回应SYN/ACK,则证明端口开放 首先是nmap 速度很快,0.67秒完成,看下wireshark的抓取 一次发送了大量的syn包 ...

  7. 如何输入x的平方

    随着电脑的普及,现在都流行在电脑上做教学课件,撰写文章,尤其是理科文献,涉及的数学符号有很多,它包括了我们常见的四则运算符号和平方.立方等,也包括了高等数学中用到的积分.极限符号等,打这些公式就需要用 ...

  8. FL Studio录制面板知识讲解

    FL Studio录制面板可以设置与录制有关的选项,它还有一个用来设置音符对齐的全局吸附选择器.刚接触水果这款音乐制作软件的同学通常不是很清楚这里的知识的,下面小编就给大家讲解一下. 1.首先,我们来 ...

  9. guitar pro系列教程(二十五):Guitar Pro教程之组织小节

    上一章节我们讲述了关于Guitar Pro 7的主界面的相关功能的介绍,对于初学作曲,又是吉他的初学者,刚刚接触Guitar Pro时,很多的功能,符号,工具都市不熟悉的,这样在创作,使用的过程中就会 ...

  10. leetcode152. 乘积最大子序列

    给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数).示例 1:输入: [2,3,-2,4]输出: 6解释: 子数组 [2,3] 有最大乘积 6.示例 2:输入: ...