Java8新特性10--其他类库的变化

 
 

Map

 public static void main(String[] arg) {
        Map map=new HashMap();
        //如果key不存在返回默认值
        System.out.println(map.getOrDefault("a",123));


        map.put("a",123);

        //将lambda结果放入该key
        map.compute("a",(key,value)-> key+""+value );

        System.out.println(map.get("a"));//a123

        //如果key不存在,则将lambda结果放入该key
        map.computeIfAbsent("a",(key)-> key+"234" );

        //如果key存在,则将lambda结果更新该key,如果lambda结果返回null,则移除该key
        map.computeIfPresent("a",(key,value)-> key+"kv"+value);//->akva123

        //如果key对应的值为null则用新value更新,否则用lambda结果更新,如果lambda的值为null,则移除此key
        //lambda表达式中参数oldvalue是原key对应的value,newvalue是第二个参数指定的值
        map.merge("a","newvalue",(oldvalue,newvalue)-> oldvalue+"dv"+newvalue);//->akva123dv

        //如果key不存在,则将值放入此key
        map.putIfAbsent("b","b123");

        //当key存在并且key对应的value等于新的值时,移除此key
        map.remove("b","b124");

        //如果存在key,则替换key的值
        map.replace("b","b125");

        //遍历
        map.forEach((key,value)->System.out.println("key:"+key+";value:"+value));
        
    }

运行结果:

123
a123
key:a;value:akva123dvnewvalue
key:b;value:b125

集合

removeIf 方法可以移除集合中满足某个谓词的所有元素。注意,这一方法与Stream API时提到的 filter 方法不大一样。Stream API中的 filter 方法会产生一个新的流,不会对当前作为数据源的流做任何变更。

列表

replaceAll 方法会对列表中的每一个元素执行特定的操作,并用处理的结果替换该元素。它的功能和Stream中的 map 方法非常相似,不过 replaceAll 会修改列表中的元素。与此相反,map 方法会生成新的元素。

比如,下面这段代码会打印输出[2,4,6,8,10],因为列表中的元素被原地修改了:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.replaceAll(x -> x * 2);
System.out.println(numbers);

Comparator

Comparator 接口现在同时包含了默认方法和静态方法。

新的实例方法包含了下面这些。

  • reversed ——对当前的 Comparator 对象进行逆序排序,并返回排序之后新的
    Comparator 对象。
  • thenComparing ——当两个对象相同时,返回使用另一个 Comparator 进行比较的
    Comparator 对象。
  • thenComparingInt 、 thenComparingDouble 、 thenComparingLong ——这些方法的工作方式和 thenComparing 方法类似,不过它们的处理函数是特别针对某些基本数据类型(分别对应于 ToIntFunction 、 ToDoubleFunction 和 ToLongFunction )的。

新的静态方法包括下面这些。

  • comparingInt 、 comparingDouble 、 comparingLong ——它们的工作方式和 compa-ring 类似,但接受的函数特别针对某些基本数据类型(分别对应于ToIntFunction 、ToDoubleFunction 和 ToLongFunction )。

  • naturalOrder ——对 Comparable 对象进行自然排序,返回一个 Comparator 对象。
    nullsFirst 、 nullsLast ——对空对象和非空对象进行比较,你可以指定空对象(null)比非空对象(non-null)小或者比非空对象大,返回值是一个 Comparator 对象。

  • reverseOrder ——和 naturalOrder().reversed() 方法类似。

并发

java.util.concurrent.atomic 包提供了多个对数字类型进行操作的类,比如 Atomic-
Integer 和 AtomicLong ,它们支持对单一变量的原子操作。这些类在Java 8中新增了更多的方
法支持。

  • getAndUpdate ——以原子方式用给定的方法更新当前值,并返回变更之前的值。
  • updateAndGet ——以原子方式用给定的方法更新当前值,并返回变更之后的值。
  • getAndAccumulate ——以原子方式用给定的方法对当前及给定的值进行更新,并返回变更之前的值。
  • accumulateAndGet ——以原子方式用给定的方法对当前及给定的值进行更新,并返回变更之后的值。

Adder 和 Accumulator
多线程的环境中,如果多个线程需要频繁地进行更新操作,且很少有读取的动作,Java API文档中推荐大家使用新的类 LongAdder 、 LongAccumulator 、DoubleAdder 以及DoubleAccumulator ,尽量避免使用它们对应的原子类型。这些新的类在设计之初就考虑了动态增长的需求,可以有效地减少线程间的竞争。

LongAddr 和 DoubleAdder 类都支持加法操作,而 LongAccumulator 和 DoubleAccu-
mulator 可以使用给定的方法整合多个值。比如,可以像下面这样使用 LongAdder 计算多个值的总和。

  public static void main(String[] arg) throws InterruptedException {
        LongAdder longAdder=new LongAdder();//初始值为0
        longAdder.add(1);//加1
        longAdder.add(2);
        System.out.println(longAdder.sum());//得到总和 3

        //使用lambda表达式积累值,初始值是0,a是lambda计算后的值,b是每次累积的值
        LongAccumulator longAccumulator=new LongAccumulator((a,b)->{
            System.out.println("a:"+a+";b:"+b);
            return a+b;//累加
        },0);
        //可以安全用于多线程环境
        for(int i=1;i<=10;i++){
            new Thread(()->longAdder.add(1)).start();//每次加1
            new Thread(()->longAccumulator.accumulate(2)).start();//每次传个2过去
        }
        Thread.sleep(2000);
        System.out.println(longAdder.sum());//13
        System.out.println(longAccumulator.get());//20

    }

运行结果:

3
a:0;b:2
a:2;b:2
a:4;b:2
a:6;b:2
a:8;b:2
a:10;b:2
a:12;b:2
a:14;b:2
a:16;b:2
a:18;b:2
13
20

ConcurrentHashMap

ConcurrentHashMap 支持三种新的操作,这些操作和你之前在流中所见的很像:

  • forEach ——对每个键值对进行特定的操作
  • reduce ——使用给定的函数,将所有的键值对整合出一个结果
  • search ——对每一个键值对执行一个函数,直到函数的返回值为一个非空值

以上每一种操作都支持四种形式,接受使用键、值、 Map.Entry 以及键值对的函数:

  • 使用键和值的操作( forEach 、 reduce 、 search )
  • 使用键的操作( forEachKey 、 reduceKeys 、 searchKeys )
  • 使用值的操作 ( forEachValue 、 reduceValues 、 searchValues )
  • 使用 Map.Entry 对象的操作( forEachEntry 、 reduceEntries 、 searchEntries )

注意,这些操作不会对 ConcurrentHashMap 的状态上锁。它们只会在运行过程中对元素进行操作。应用到这些操作上的函数不应该对任何的顺序,或者其他对象,抑或在计算过程发生变化的值,有依赖。

除此之外,你需要为这些操作指定一个并发阈值。如果经过预估当前 map 的大小小于设定的阈值,操作会顺序执行。使用值 1 开启基于通用线程池的最大并行。使用值 Long.MAX_VALUE 设定程序以单线程执行操作。

下面这个例子中,我们使用 reduceValues 试图找出 map 中的最大值:

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
Optional<Integer> maxValue = Optional.of(map.reduceValues(1, Integer::max));

ConcurrentHashMap 类还提供了一个新的方法,名叫 mappingCount ,它以长整型 long 返回map 中映射的数目。我们应该尽量使用这个新方法,而不是老的 size 方法, size 方法返回的类型为 int 。这是因为映射的数量可能是 int 无法表示的。

ConcurrentHashMap 类还提供了一个名为 KeySet 的新方法,该方法以 Set 的形式返回ConcurrentHashMap 的一个视图(对 map 的修改会反映在该 Set 中,反之亦然)。你也可以使用新的静态方法 newKeySet ,由 ConcurrentHashMap 创建一个 Set 。

Number

Java 8 API对 Number 和 Math 也做了改进,为它们增加了新的方法。
Number 类中新增的方法如下:

  • Short 、 Integer 、 Long 、 Float 和 Double 类提供了静态方法 sum 、 min 和 max
    Integer 和 Long 类提供了 compareUnsigned 、 divideUnsigned 、remainderUnsigned和 toUnsignedLong 方法来处理无符号数。
  • Integer 和 Long 类也分别提供了静态方法 parseUnsignedInt 和 parseUnsignedLong
    将字符解析为无符号 int 或者 long 类型。
  • Byte 和 Short 类提供了 toUnsignedInt 和 toUnsignedLong 方法通过无符号转换将参
    数 转 化 为 int 或 者 long 类 型 。 类 似 地 , Integer 类 现 在 也 提 供 了 静 态 方 法toUnsignedLong 。
  • Double 和 Float 类提供了静态方法 isFinite ,可以检查参数是否为有限浮点数。
  • Boolean 类现在提供了静态方法 logicalAnd 、 logicalOr 和 logicalXor ,可以在两个
    boolean 之间执行 and 、 or 和 xor 操作。
  • BigInteger 类提供了 byteValueExact 、 shortValueExact 、 intValueExact 和
    longValueExact ,可以将 BigInteger 类型的值转换为对应的基础类型。不过,如果在转换过程中有信息的丢失,方法会抛出算术异常。

Math

如果 Math 中的方法在操作中出现溢出, Math 类提供了新的方法可以抛出算术异常。支持这一异常的方法包括使用 int 和 long 参数的 addExact 、 subtractExact 、 multipleExact 、incrementExact 、 decrementExact 和 negateExact 。此外, Math 类还新增了一个静态方法toIntExact ,可以将 long 值转换为 int 值。其他的新增内容包括静态方法 floorMod 、 floorDiv和 nextDown 。

Files

Files 类最引人注目的改变是,你现在可以用文件直接产生流。新的静态方法 Files.lines ,通过该方法你可以以延迟方式读取文件的内容,并将其作为一个流。此外,还有一些非常有用的静态方法可以返回流。

  • Files.list ——生成由指定目录中所有条目构成的 Stream<Path> 。这个列表不是递归包含的。由于流是延迟消费的,处理包含内容非常庞大的目录时,这个方法非常有用。
  • Files.walk ——和 Files.list 有些类似,它也生成包含给定目录中所有条目的Stream<Path> 。不过这个列表是递归的,你可以设定递归的深度。注意,该遍历是依照深度优先进行的。
  • Files.find ——通过递归地遍历一个目录找到符合条件的条目,并生成一个Stream<Path> 对象。

String

String 类也新增了一个静态方法,名叫 join 。它可以用一个分隔符将多个字符串连接起来。你可以像下面这样使用它:
String authors = String.join("," , "Raoul", "Mario", "Alan");



作者:不迷失
链接:https://www.jianshu.com/p/025a969cc8a8
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值