以下代码片段是获取目录列表的方法的一部分,在每个文件上调用extract方法并将生成的药物对象序列化为xml.
try(Stream<Path> paths = Files.list(infoDir)) {
paths
.parallel()
.map(this::extract)
.forEachOrdered(drug -> {
try {
marshaller.write(drug);
} catch (JAXBException ex) {
ex.printStackTrace();
}
});
}
Run Code Online (Sandbox Code Playgroud)
这是完全相同的完全相同的代码,但使用普通.list()调用来获取目录列表并调用.parallelStream()结果列表.
Arrays.asList(infoDir.toFile().list())
.parallelStream()
.map(f -> infoDir.resolve(f))
.map(this::extract)
.forEachOrdered(drug -> {
try {
marshaller.write(drug);
} catch (JAXBException ex) {
ex.printStackTrace();
}
});
Run Code Online (Sandbox Code Playgroud)
我的机器是四核MacBook Pro,Java v 1.8.0_60(内置1.8.0_60-b27).
我正在处理~7000个文件.平均3次运行:
第一版:有.parallel():20秒.没有.parallel():41秒
第二版:带.parallelStream():12秒.用.stream():41秒.
并行模式下的那8秒似乎是一个巨大的差异,因为extract从流中读取并完成所有繁重工作的方法和write执行最终写入的调用都没有改变.
假设我正在处理自定义收集器并假设accumulator 总是会在供应商返回的集合中添加一些元素,是否有可能在combiner调用时,其中一个中间结果将为空?一个例子可能更容易理解.
假设我有一个List数字,我想将它拆分为列表列表,其中2是分隔符.所以例如我有1, 2, 3, 4, 2, 8,结果应该是[[1], [3, 4], [8]].这实现起来并不复杂(不要过多地判断代码,我写了一些快速的东西,所以我可以写这个问题).
List<List<Integer>> result = Stream.of(1, 2, 3, 4, 2, 8)
.collect(Collector.of(
() -> new ArrayList<>(),
(list, elem) -> {
if (list.isEmpty()) {
List<Integer> inner = new ArrayList<>();
inner.add(elem);
list.add(inner);
} else {
if (elem == 2) {
list.add(new ArrayList<>());
} else {
List<Integer> last = list.get(list.size() - 1);
last.add(elem);
}
}
},
(left, …Run Code Online (Sandbox Code Playgroud) 为什么以下代码:
StringBuilder sb22 = IntStream
.range(1, 101)
.filter(x -> x > 50)
.boxed()
.parallel()
.collect(// object that is used in accumulator to do accumulating on
StringBuilder::new,
// use object from above and call append on it with each stream element as argument
(sb, a) -> sb.append(":" + a),
// (executes only when using parallel!)
(sb1, sb2) -> {
System.out.println(Thread.currentThread().getId() + " " + "sb1=" + sb1 + " AND " + "sb2=" + sb2);
sb1.append("-"+sb2);
});
Run Code Online (Sandbox Code Playgroud)
产生这个结果:
------------------:51:52:53-:54:55:56-:57:58:59-:60:61:62-:63:64:65-:66:67:68-:69:70:71-:72:73-:74:75-:76:77:78-:79:80:81-:82:83:84-:85:86:87-:88:89:90-:91:92:93-:94:95:96-:97:98-:99:100
Run Code Online (Sandbox Code Playgroud)
不应该首先将part(------------------ …
如何使用Java 8流方法(例如,对于数组,创建一个求值的地方),以惯用方式枚举Stream<T>哪个T实例将每个实例映射到一个唯一的整数?T[] valuesMap<T,Integer>Map.get(values[i]) == itrue
目前,我正在定义一个匿名类,它增加一个int字段以便与该Collectors.toMap(..)方法一起使用:
private static <T> Map<T, Integer> createIdMap(final Stream<T> values) {
return values.collect(Collectors.toMap(Function.identity(), new Function<T, Integer>() {
private int nextId = 0;
@Override
public Integer apply(final T t) {
return nextId++;
}
}));
}
Run Code Online (Sandbox Code Playgroud)
但是,使用Java 8流API是否没有更简洁/更优雅的方式? - 如果可以安全地并行化,则可获得奖励积分.
问题很简单:为什么我们不能在流中的操作中使用StringBuilder(...)as ,但可以用作?identity functionreduce(...)java8string1.concat(string2)identity function
string1.concat(string2)可以看作是相似的builder.append(string)(虽然可以理解为这些操作几乎没有区别),但是我无法理解reduce操作的区别。考虑以下示例:
List<String> list = Arrays.asList("1", "2", "3");
// Example using the string concatenation operation
System.out.println(list.stream().parallel()
.reduce("", (s1, s2) -> s1 + s2, (s1, s2)->s1 + s2));
// The same example, using the StringBuilder
System.out.println(list.stream() .parallel()
.reduce(new StringBuilder(""), (builder, s) -> builder
.append(s),(builder1, builder2) -> builder1
.append(builder2)));
// using the actual concat(...) method
System.out.println(list.stream().parallel()
.reduce("", (s1, s2) -> s1.concat(s2), (s1, s2)->s1.concat(s2)));
Run Code Online (Sandbox Code Playgroud)
这是执行上述行后的输出:
123
321321321321 // output when …Run Code Online (Sandbox Code Playgroud)