Глубокое сравнение каждого элемента в массиве - PullRequest
0 голосов
/ 17 ноября 2018

У меня есть следующие 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 и лямбда-функции, например:

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.0 Checking 3.0 with 5.0 Checking 3.0 with 3.0 Checking 5.0 with 3.0 Checking 5.0 with 5.0 Checking 5.0 with 3.0 Checking 3.0 with 3.0 Checking 3.0 with 5.0 Checking 3.0 with 3.0

Как вы можете видеть, это следует алгоритму O (n²), который я не использую.В моем исходном коде я «пропускал» элементы, которые я уже проверял, используя индексы из внешнего вложенного цикла for.Так что мой вопрос, есть ли способ как-то реализовать это во вложенной <Stream>.anyMatch(...), которую я пытался.Или есть более чистый способ сделать это?

1 Ответ

0 голосов
/ 17 ноября 2018

Вы можете повторить метод duplicate, используя Stream API, следующим образом:

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);
...