有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java将并行数组流简化为单个数组

我试图减少阵列流的并行流<;ArrayList>;放入单个数组ArrayList中 我使用累加器和组合器的reduce方法,如下所示:-

    public static void main(String [] args) {
        ArrayList<String> l1 = new ArrayList<>();
        l1.add("a1");
        l1.add("a2");
        
        List<String> l2 = new ArrayList<>();
        l2.add("a3");
        l2.add("a4");
                
        List<List<String>> l = new ArrayList<>();
        l.add(l1);
        l.add(l2);
        
        Stream<List<String>> stream = l.stream();
        join(stream).forEach(System.out::println);
}

private  static  <T> List<T> join(Stream<List<T>> stream) {
        return stream.parallel().reduce(new ArrayList<>(),  (total, element) -> {
            System.out.println("total: " + total);
            System.out.println("element: " + element);
            total.addAll(element);
            return total;
        },  (total1, total2) -> {
            System.out.println("total1: " + total1);
            System.out.println("total2: " + total2);
            total1.addAll(total2);
            return total1;
        });
}

我知道合并器用于合并并行流。。但它并没有像我预期的那样起作用, 因为我得到了如下重复的结果:-

total: []
element: [a3, a4]
total: []
element: [a1, a2]
total1: [a3, a4, a1, a2]
total2: [a3, a4, a1, a2]
a3
a4
a1
a2
a3
a4
a1
a2

那么为什么结果是重复的呢?在累加器中使用数组列表也是线程安全的吗


共 (1) 个答案

  1. # 1 楼答案

    您应该只使用flatMap

    Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream. (If a mapped stream is null an empty stream is used, instead.)

    This is an intermediate operation.

    l.stream().flatMap(x -> x.stream()).collect(Collectors.toList()); // is [a1, a2, a3, a4]
    

    l.stream().flatMap(List::stream).collect(Collectors.toList());
    

    代码的问题在于,您将函数式代码与副作用混为一谈。这不是好兆头。如果消除了副作用,则输出与预期一致:

        private static <T> List<T> join(Stream<List<T>> stream) {
            return stream.parallel().reduce(new ArrayList<>(), (total, element) -> {
                System.out.println("total: " + total);
                System.out.println("element: " + element);
                //total.addAll(element);
                //return total;
                var list = new ArrayList<T>(total);
                list.addAll(element);
                return list;
            }, (total1, total2) -> {
                System.out.println("total1: " + total1);
                System.out.println("total2: " + total2);
                //total1.addAll(total2);
                //return total1;
                var list = new ArrayList<T>(total1);
                list.addAll(total2);
                return list;
            });
        }
    

    您还应该避免使用parallel(),除非您有明确、客观的理由这样做。并行性是一种开销,只有当有繁重的工作要做时,它才会变得更高效。否则,同步开销将是比任何收益更大的损失