Java8 In Action-附录B.类库的更新

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/G0_hw/article/details/82952101

B.1 集合
Collection API在Java 8中最重大的更新就是引入了流,除此之外,Collection API还有一部分更新.

B.1.1 其他新增的方法
在这里插入图片描述

1. Map
Map接口的变化最大,它增加了多个新方法,利用这些新方法能更加便利地操纵Map中的数据。

//getOrDefault方法就可以替换现在检测Map中是否包含给定键映射的惯用方法。
//如果Map中不存在这样的键映射,你可以提供一个默认值,方法会返回该默认值
//Java8之前的版本
Map<String, Integer> carInventory = new HashMap<>();
Integer count = 0;
if(map.containsKey("Aston Martin")){
count = map.get("Aston Martin");
}

public String getData(String url){
String data = cache.get(url);
if(data == null){
data = getData(url);
cache.put(url, data);
}
return data;
}

//Java8之后的版本
Integer count = map.getOrDefault("Aston Martin", 0);

public String getData(String url){
return cache.computeIfAbsent(url, this::getData);
}

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

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

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.replaceAll(x -> x * 2);
System.out.println(numbers);//打印输出[2,4,6,8,10]

B.1.2 Collections 类

B.1.3 Comparator
Comparator接口现在同时包含了默认方法和静态方法。静态方法Comparator.comparing返回一个Comparator对象,该对象提供了一个函数可以提取排序关键字。
新的实例方法包含了下面这些。
 reversed——对当前的Comparator 对象进行逆序排序, 并返回排序之后新的Comparator对象。
 thenComparing——当两个对象相同时,返回使用另一个Comparator进行比较的Comparator对象。
 thenComparingInt、thenComparingDouble、thenComparingLong——这些方法的工作方式和thenComparing方法类似,不过它们的处理函数是特别针对某些基本数据类型(分别对应于ToIntFunction、ToDoubleFunction和ToLongFunction)的。新的静态方法包括下面这些。
 comparingInt、comparingDouble、comparingLong——它们的工作方式和comparing类似,但接受的函数特别针对某些基本数据类型(分别对应于ToIntFunction、ToDoubleFunction和ToLongFunction)。
 naturalOrder——对Comparable对象进行自然排序,返回一个Comparator对象。
 nullsFirst、nullsLast——对空对象和非空对象进行比较,你可以指定空对象(null)比非空对象(non-null)小或者比非空对象大,返回值是一个Comparator对象。
 reverseOrder——和naturalOrder().reversed()方法类似。

B.2 并发
B.2.1 原子操作
java.util.concurrent.atomic包提供了多个对数字类型进行操作的类,比如AtomicInteger和AtomicLong,它们支持对单一变量的原子操作。这些类在Java 8中新增了更多的方法支持。
 getAndUpdate——以原子方式用给定的方法更新当前值,并返回变更之前的值。
 updateAndGet——以原子方式用给定的方法更新当前值,并返回变更之后的值。
 getAndAccumulate——以原子方式用给定的方法对当前及给定的值进行更新,并返回变更之前的值。
 accumulateAndGet——以原子方式用给定的方法对当前及给定的值进行更新,并返回变更之后的值。

//原子方式比较一个现存的原子整型值和一个给定的观测值(比如10),并将变量设定为二者中较小的一个。
int min = atomicInteger.accumulateAndGet(10, Integer::min);

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

//使用LongAdder计算多个值之和
LongAdder adder = new LongAdder();//默认构造器,初始的sum值被置为0
adder.add(10);
// …在多个不同的线程中进行加法运算
long sum = adder.sum();

//使用LongAccumulator计算多个值之和
LongAccumulator acc = new LongAccumulator(Long::sum, 0);
acc.accumulate(10);
// …在几个不同的线程中累计计算值
long result = acc.get();

B.2.2 ConcurrentHashMap

  1. 性能
    为了改善性能,要对ConcurrentHashMap的内部数据结构进行调整。典型情况下,map的条目会被存储在桶中,依据键生成哈希值进行访问。但是,如果大量键返回相同的哈希值,由于桶是由List实现的,它的查询复杂度为O(n),这种情况下性能会恶化。在Java 8中,当桶过于臃肿时,它们会被动态地替换为排序树(sorted tree),新的数据结构具有更好的查询性能(排序树的查询复杂度为O(log(n)))。注意,这种优化只有当键是可以比较的(比如String或者Number类)时才可能发生。
  2. 类流操作
    ConcurrentHashMap支持三种新的操作:
     forEach——对每个键值对进行特定的操作
     reduce——使用给定的精简函数(reduction function),将所有的键值对整合出一个结果
     search——对每一个键值对执行一个函数,直到函数的返回值为一个非空值
//使用reduceValues试图找出map中的最大值
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
Optional<Integer> maxValue = Optional.of(map.reduceValues(1, Integer::max));
//注意,对int、long和double,它们的reduce操作各有不同(比如reduceValuesToInt、reduceKeysToLong等)
  • 计数
    ConcurrentHashMap类提供了一个新的方法,名叫mappingCount,它以长整型long返回map中映射的数目。我们应该尽量使用这个新方法,而不是老的size方法,size方法返回的类型为int。这是因为映射的数量可能是int无法表示的。
  • 集合视图
    ConcurrentHashMap类还提供了一个名为KeySet的新方法,该方法以Set的形式返回ConcurrentHashMap的一个视图(对map的修改会反映在该Set中,反之亦然)。你也可以使用新的静态方法newKeySet,由ConcurrentHashMap创建一个Set。

B.3 Arrays
Arrays类提供了不同的静态方法对数组进行操作。现在,它又包括了四个新的方法(它们都有特别重载的变量)。

  • parallelSort
  • setAll
  • parallelSetAll
  • parallelPrefix

B.4 Number 和Math

B.5 Files
Files类最引人注目的改变是,你现在可以用文件直接产生流。
 Files.lines——以延迟方式读取文件的内容,并将其作为一个流.
 Files.list——生成由指定目录中所有条目构成的Stream 。这个列表不是递归包含的。由于流是延迟消费的,处理包含内容非常庞大的目录时,这个方法非常有用。
 Files.walk——和Files.list有些类似,它也生成包含给定目录中所有条目的Stream<Path>。不过这个列表是递归的,你可以设定递归的深度。注意,该遍历是依照深度优先进行的。
 Files.find——通过递归地遍历一个目录找到符合条件的条目, 并生成一个Stream<Path>对象。

B.6 Reflection
注解机制的变化.
新增了可以查询方法参数信息的API,使用新增的java.lang.reflect.Parameter类查询方法参数的名称和修饰.

B.7 String
String类也新增了一个静态方法,名叫join。

String authors = String.join(", ", "Raoul", "Mario", "Alan");
System.out.println(authors);

猜你喜欢

转载自blog.csdn.net/G0_hw/article/details/82952101