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

Java8新特性10--其他类库的变化_第1张图片
21e610bd65f6d2693ec165b05927730b

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

String

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

@不迷失|知识改善生活

微信公众号:java技术

Java8新特性10--其他类库的变化_第2张图片
1492957339

专注技术研究与视频教学,分享有价值的技术与经验,关注程序员的发展!

技术博客:http://bumishi.cn

技术交流群:245130488

@不迷失教学视频

Java8新特性10--其他类库的变化_第3张图片
xiaoetong_qrcode

Java8新特性10--其他类库的变化_第4张图片
qqketang_qrcode

腾讯课堂: http://bumishi.ke.qq.com

Java8新特性10--其他类库的变化_第5张图片
baiduketang_qrcode

百度课堂: http://chuanke.com/s3377987.html

你可能感兴趣的:(Java8新特性10--其他类库的变化)