Java8的这些集合骚操作,你掌握了嘛?

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

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

Java8的这些集合骚操作,你掌握了嘛?

Iterable的forEach

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

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

1 default void forEach(Consumer<? super T> action) { 2 Objects.requireNonNull(action); 3 for (T t : this) { 4 action.accept(t); 5 } 6 }

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

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

Iterator的forEachRemaining

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

1public interface Iterator<E> { 2 3 boolean hasNext(); 4 5 E next(); 6 7 default void remove() { 8 throw new UnsupportedOperationException("remove"); 9 } 10 11 default void forEachRemaining(Consumer<? super E> action) { 12 Objects.requireNonNull(action); 13 while (hasNext()) 14 action.accept(next()); 15 } 16}

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

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

Collection的removeIf

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

1 default boolean removeIf(Predicate<? super E> filter) { 2 Objects.requireNonNull(filter); 3 boolean removed = false; 4 final Iterator<E> each = iterator(); 5 while (each.hasNext()) { 6 // 判断元素是否需要被移除 7 if (filter.test(each.next())) { 8 each.remove(); 9 removed = true; 10 } 11 } 12 return removed; 13 }

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

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

Stream操作

具体使用可以参照

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

List的replaceAll

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

1 default void replaceAll(UnaryOperator<E> operator) { 2 Objects.requireNonNull(operator); 3 final ListIterator<E> li = this.listIterator(); 4 while (li.hasNext()) { 5 li.set(operator.apply(li.next())); 6 } 7 }

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

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

List的sort

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

1 default void sort(Comparator<? super E> c) { 2 Object[] a = this.toArray(); 3 Arrays.sort(a, (Comparator) c); 4 ListIterator<E> i = this.listIterator(); 5 for (Object e : a) { 6 i.next(); 7 i.set((E) e); 8 } 9 }

下面这个例子将list逆序。

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

Map的ForEach

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

1 default void forEach(BiConsumer<? super K, ? super V> action) { 2 Objects.requireNonNull(action); 3 for (Map.Entry<K, V> entry : entrySet()) { 4 K k; 5 V v; 6 try { 7 k = entry.getKey(); 8 v = entry.getValue(); 9 } catch(IllegalStateException ise) { 10 // this usually means the entry is no longer in the map. 11 throw new ConcurrentModificationException(ise); 12 } 13 action.accept(k, v); 14 } 15 }

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

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

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

1 Map<Integer, String> map = new HashMap<>(); 2 3 { 4 map.put(1, "hello"); 5 map.put(2, "summer"); 6 map.put(3, "day"); 7 map.put(4, "tqbx"); 8 }

Map的remove

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

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

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

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

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对。

    1@Test 2public void testCompute() { 3 //key==2 对应的value存在时,使用计算的结果作为新value 4 map.computeIfPresent(2, (k, v) -> v.toUpperCase()); 5 print(map); 6 7 //key==6 对应的value为null (或不存在)时,使用计算的结果作为新value 8 map.computeIfAbsent(6, (k) -> k + "haha"); 9 print(map); 10}

Map的getOrDefault

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

Map的merge

1 default V merge(K key, V value, 2 BiFunction<? super V, ? super V, ? extends V> remappingFunction) { 3 Objects.requireNonNull(remappingFunction); 4 Objects.requireNonNull(value); 5 // 先获取原值 6 V oldValue = get(key); 7 // 原值为null,新值则为传入的value,不为null,则使用function计算,得到新值 8 V newValue = (oldValue == null) ? value : 9 remappingFunction.apply(oldValue, value); 10 // 新值如果为null,则移除原key-value对 11 if(newValue == null) { 12 remove(key); 13 } else { 14 // 不为null,则替换之 15 put(key, newValue); 16 } 17 // 返回新值 18 return newValue; 19 } 20 21 22 @Test 23 public void testMerge(){ 24 // key为2 的值 加上 +add 25 map.merge(2," + add",(oldval, newVal) -> oldval + newVal); 26 print(map); 27 }

Map的putIfAbsent

1 default V putIfAbsent(K key, V value) { 2 // 得到原值 3 V v = get(key); 4 // 原值为null,则替换新值 5 if (v == null) { 6 v = put(key, value); 7 } 8 // 返回原值 9 return v; 10 } 11 12 13 @Test 14 public void testPutIfAbsent(){ 15 // key = 10 对应的value不存在, 则用101010 覆盖 16 String s1 = map.putIfAbsent(10, "101010"); 17 System.out.println(s1); 18 print(map); 19 System.out.println("============================"); 20 // key = 2 对应的value存在且为summer,返回summer 21 String s2 = map.putIfAbsent(2, "2222"); 22 System.out.println(s2); 23 print(map); 24 }

输出结果

1null 2x -> 1, y -> hello 3x -> 2, y -> summer 4x -> 3, y -> day 5x -> 4, y -> tqbx 6x -> 10, y -> 101010 7============================ 8summer 9x -> 1, y -> hello 10x -> 2, y -> summer 11x -> 3, y -> day 12x -> 4, y -> tqbx 13x -> 10, y -> 101010

Map的replace相关方法

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

输出结果:

1x -> 1, y -> hi 2x -> 2, y -> summer 3x -> 3, y -> day 4x -> 4, y -> tqbx 5============================ 6x -> 1, y -> hi 7x -> 2, y -> 天乔巴夏 8x -> 3, y -> day 9x -> 4, y -> tqbx 10============================ 11x -> 1, y -> 1-HI 12x -> 2, y -> 2-天乔巴夏 13x -> 3, y -> 3-DAY 14x -> 4, y -> 4-TQBX

原文:https://www.cnblogs.com/summerday152/p/14129448.html

如果觉得本文对你有帮助,可以关注一下我公众号,回复关键字【面试】即可得到一份Java核心知识点整理与一份面试大礼包!另有更多技术干货文章以及相关资料共享,大家一起学习进步!

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Java日期时间API系列31

  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前