我有以下3个文件,

A.java:

class A {

    private float b;

    public A(float b) {
        this.b = b;
    }

    public float getB() {
        return b;
    }

    public String toString() {
        return "A(b = " + b + ")";
    }

}

C.java:
import java.util.Arrays;

class C {

    private A[] d;
    private int i = 0;

    public C() {
        d = new A[5];
    }

    public void addB(A b) {
        d[i++] = b;
    }

    public String toString() {
        return "C(b = " + Arrays.toString(d) + ")";
    }

    public void duplicate() {
        A temp[] = Arrays.copyOf(d, d.length);
        for (int cur = 0; cur < d.length; cur++) {
            if (d[cur] == null) continue;
            float currB = d[cur].getB();
            for (int nxt = cur + 1; nxt < d.length; nxt++) {
                if(d[nxt] == null) continue;
                if(currB == d[nxt].getB()) {
                    temp[i++] = new A(currB * 0.5f);
                }
            }
        }
        d = temp;
    }
}

D.java:
class D {

    public static void main(String[] args) {
        C c = new C();
        c.addB(new A(3));
        c.addB(new A(5));
        c.addB(new A(3));
        System.out.println(c.toString()); // C(b = [A(b = 3.0), A(b = 5.0), A(b = 3.0), null, null])
        c.duplicate();
        System.out.println(c.toString()); // C(b = [A(b = 3.0), A(b = 5.0), A(b = 3.0), A(b = 1.5), null])

    }

}

这可以达到我的预期,即如果其中两个元素从b返回的浮点数相同,则将另一项添加到一半A.getB()的数组中。但是,我试图使用花哨的Java 8流方法和lambda函数来实现此目标,如下所示:
Arrays.stream(d).anyMatch(cur -> {
    if (cur == null) return false;
    Arrays.stream(d).anyMatch(nxt -> {
        if (nxt == null) return false;
        System.out.println("Checking " + cur.getB() + " with " + nxt.getB());
        return false;
    });
    return false;
});

并输出:
Checking 3.0 with 3.0Checking 3.0 with 5.0Checking 3.0 with 3.0Checking 5.0 with 3.0Checking 5.0 with 5.0Checking 5.0 with 3.0Checking 3.0 with 3.0Checking 3.0 with 5.0Checking 3.0 with 3.0
如您所见,这遵循O(n²)算法,这不是我想要的。在我的原始代码中,我正在“跳过”使用外部嵌套的for循环中的索引已经检查过的元素。所以我的问题是,是否有办法以某种方式在我尝试的嵌套<Stream>.anyMatch(...)中实现它。还是有一种更清洁的方法?

最佳答案

您可以使用Stream API复制duplicate方法,如下所示:

Stream<A> result =
       IntStream.range(0, d.length)
                .filter(cur -> d[cur] != null)
                .flatMap(cur -> IntStream.range(cur + 1, d.length)
                        .filter(nxt -> d[nxt] != null)
                        .filter(nxt -> d[cur].getB() == d[nxt].getB())
                        .map(i -> cur))
                .mapToObj(cur -> new A(d[cur].getB() * 0.5f));

d = Stream.concat(Arrays.stream(d), result)
          .toArray(A[]::new);

10-08 20:18