Parallel Stream
Stream 有串行和并行两种,串行 Stream 上的操作是在一个线程中依次完成,而并行 Stream 则是在多个线程上同时执行。
下面的例子展示了如何通过并行 Stream 来提升性能:
首先创建一个没有重复元素的大集合:
代码语言:javascript复制int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i = 0; i < max; i ) {
UUID uuid = UUID.randomUUID();
values.add(uuid.toString());
}
分别用串行和并行两种方式对其进行排序,最后看看所用时间的对比。
Sequential Sort(串行排序)
代码语言:javascript复制// 串行排序
long t0 = System.nanoTime();
long count = values.stream().sorted().count();
System.out.println(count);
long t1 = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("sequential sort took: %d ms", millis));
代码语言:javascript复制1000000
sequential sort took: 709 ms // 串行排序所用时间
Parallel Sort(并行排序)
代码语言:javascript复制// 并行排序
long t0 = System.nanoTime();
long count = values.parallelStream().sorted().count();
System.out.println(count);
long t1 = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("parallel sort took: %d ms", millis));
代码语言:javascript复制1000000
parallel sort took: 475 ms // 串行排序所用的时间
上面两个代码几乎是一样的,但是并行版的快了 50% 左右,唯一需要做的改动就是将 stream()
改为 parallelStream()
。
Map
之前提到过,Map 类型不支持 streams,不过 Map 提供了一些新的有用的方法来处理一些日常任务。Map 接口本身没有可用的 stream()
方法,但允许在键或者值上创建专门的流,如 map.keySet().stream()
,map.values().stream()
和map.entrySet().stream()
。
Map<Integer, String> map = new HashMap<>();
for (int i = 0; i < 10; i ) {
map.putIfAbsent(i, "val" i);
}
map.forEach((id, val) -> System.out.println(val)); // val0 val1 val2 val3 val4 val5 val6 val7 val8 val9
putIfAbsent
阻止在 null 检查时写入额外的代码;
forEach
接受一个 consumer 来对 map 中的每个元素进行操作。
此示例展示如了何使用函数在 map 上计算代码:
代码语言:javascript复制map.computeIfPresent(3, (num, val) -> val num);
map.get(3); // val33
map.computeIfPresent(9, (num, val) -> null);
map.containsKey(9); // false
map.computeIfAbsent(23, num -> "val" num);
map.containsKey(23); // true
map.computeIfAbsent(3, num -> "bam");
map.get(3); // val33
接下来展示如何在 Map 里删除一个键值全都匹配的项:
代码语言:javascript复制map.remove(3, "val3");
map.get(3); // val33
map.remove(3, "val33");
map.get(3); // null
另外一个有用的方法:
代码语言:javascript复制map.getOrDefault(42, "not found"); // not found
对 Map 的元素做合并也变得很容易了:
代码语言:javascript复制map.merge(9, "val9", (value, newValue) -> value.concat(newValue));
map.get(9); // val9
map.merge(9, "concat", (value, newValue) -> value.concat(newValue));
map.get(9); // val9concat
Merge 做的事情是:如果键名不存在,则插入,否则对原键对应的值做合并操作,并重新插入到 map 中。