Parallel Stream 和 Map

2019-08-02 10:42:03 浏览数 (1)

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()

代码语言:javascript复制
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 中。

0 人点赞