Java 深入比较数组中的每个元素

Java 深入比较数组中的每个元素,java,java-8,java-stream,Java,Java 8,Java Stream,我有以下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

我有以下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;
    }
}
这就是我期望它做的,即如果两个元素从
A.getB()
返回相同的浮点值,则使用
b
的一半向数组中添加另一项。然而,我试图使用花哨的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;
});
这个输出:

用3.0检查3.0
用5.0检查3.0
用3.0检查3.0
用3.0检查5.0
用5.0检查5.0
用3.0检查5.0
用3.0检查3.0
用5.0检查3.0
用3.0检查3.0


正如你所看到的,这遵循了O(n²)算法,这不是我想要的。在我的原始代码中,我“跳过”了我已经使用外部嵌套for循环的索引检查过的元素。所以我的问题是,在我尝试的嵌套
.anyMatch(…)
中,是否有某种方法可以实现这一点。或者有更干净的方法吗?

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

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);
流结果=
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->newa(d[cur].getB()*0.5f));
d=Stream.concat(Arrays.Stream(d),result)
.toArray(A[]::新的);

您是否尝试使用streams API复制
复制
方法?具有相同的时间复杂度还是更好?@Aomine
duplicate
只是我随机想到的方法名称,所以不。不谈方法名称,我想问的是复制方法的逻辑是你试图复制的吗?或者您只是想改进代码片段
Arrays.stream(d).anyMatch(cur->{………
?@Aomine啊,好吧,对不起,我误解了。所以,是的,这是正确的,我正在尝试复制最后一个代码段上的
duplicate
方法中的逻辑。我的第一个问题或第二个问题…?谢谢。你能简要解释一下
IntStream.range(cur+1,d.length)的用途吗
是吗?它只是从
cur+1
d.length
独占生成一个
IntStream
数字,也就是说,就像在你的代码
中为(intnxt=cur+1;nxt
@newbie>生成的一样
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);