将两个流与整理相结合

时间:2015-03-25 15:29:03

标签: java lambda java-8 java-stream

我需要以高效灵活的方式完成一些Matrix工作,并希望我可以使用流和lambda来练习Java 8,甚至可以从中获得自由并行性。我正在努力的一点是如何在两个流上执行操作,将结果放入第三个。

考虑一下简单的机制:

static final List<String> a = Arrays.asList("A", "A", "A");
static final List<String> b = Arrays.asList("B", "B", "B");

public void withoutStreams() {
    // The boring old way.
    List<String> c = new ArrayList<>();
    for (Iterator<String> ai = a.iterator(), bi = b.iterator(); ai.hasNext() && bi.hasNext();) {
        c.add(ai.next() + bi.next());
    }
    System.out.println(c);
}

工作正常,但我想使用Streams。

private void withStreams() {
    List<String> c = new ArrayList<>();
    combine(a.stream(), b.stream(), c, (String x, String y) -> x + y);
}

private void combine(Stream<String> a, Stream<String> b, List<String> c, BinaryOperator<String> op) {
    // What can I do here to make it happen?
}

我完全希望我们将使用某种形式的c来填充Consumer,但是除了使用(row,col)之外,还有一些额外的荣誉可以用来指代矩阵的特定单元格。记住细胞是不可变的。

2 个答案:

答案 0 :(得分:4)

您可以使用IntStream类来模拟索引,然后使用.mapToObj连接来自ab的索引对象:

List<String> list = IntStream.range(0, Math.max(a.size(), b.size()))
                             .mapToObj(i -> a.get(i) + b.get(i))
                             .collect(Collectors.toList());

应用于您的方法,它将如下所示:

private void combine(List<String> a, List<String> b, List<String> c, BinaryOperator<String> op) {
    c = IntStream.range(0, Math.max(a.size(), b.size()))
                 .mapToObj(i -> op.apply(a.get(i), b.get(i)))
                 .collect(Collectors.toList());
}

但是,如果您不想更改方法的签名,here is a solution which works for all possible combinations of infinite and finite streams

private void combine(Stream<String> a, Stream<String> b, List<String> c, BinaryOperator<String> op) {
    Iterator<String> i1 = a.iterator();
    Iterator<String> i2 = b.iterator();
    Iterable<String> i = () -> new Iterator<String>() {
        public boolean hasNext() {
            return i1.hasNext() && i2.hasNext();
        }
        public String next() {
            return op.apply(i1.next(), i2.next());
        }
    };
    c = StreamSupport.stream(i.spliterator(), false).collect(Collectors.toList());
}

答案 1 :(得分:1)

函数式编程风格,使用递归(无循环):

static Stream<String> combine(List<String> a, List<String> b) {
    if(a.isEmpty() ||  b.isEmpty()) {
        return Stream.empty();
    }

    return Stream.concat(
            Stream.of(a.get(0) + b.get(0)),
            combine(a.stream().skip(1).collect(Collectors.toList()), 
                    b.stream().skip(1).collect(Collectors.toList()))
            );
}

加:我投票支持kocko的回答,我的答案是为了好玩。