相关疑难解决方法(0)

为什么Files.list()并行流的执行速度比使用Collection.parallelStream()慢得多?

以下代码片段是获取目录列表的方法的一部分,在每个文件上调用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执行最终写入的调用都没有改变.

java parallel-processing nio java-8 java-stream

19
推荐指数
2
解决办法
2284
查看次数

流收集累加器/合并器命令

这基本上是这个答案的后续行动.

假设我正在处理自定义收集器并假设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)

java java-8 java-stream

9
推荐指数
1
解决办法
249
查看次数

Java流 - 收集组合器

为什么以下代码:

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 java-stream collectors

6
推荐指数
1
解决办法
254
查看次数

在Java 8中以惯用方式枚举对象流

如何使用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是否没有更简洁/更优雅的方式? - 如果可以安全地并行化,则可获得奖励积分.

java enumeration java-8 java-stream

4
推荐指数
1
解决办法
182
查看次数

在 reduce 操作中使用 StringBuilder(...) 作为标识值会产生不可预测的结果

问题很简单:为什么我们不能在流中的操作中使用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)

java parallel-processing reduce java-8 java-stream

2
推荐指数
1
解决办法
151
查看次数