Wie überprüfe ich, ob zwei Streams nicht verbunden sind?

Nov 23 2020

Ich möchte mit Streams vergleichen und prüfen, ob sie 1 oder mehr Elemente gemeinsam haben (1 zu finden ist ausreichend, um nicht mehr nach mehr zu suchen). Ich möchte dies auf Streams anwenden können, die eine benutzerdefinierte Klasse enthalten.

Nehmen wir zur Veranschaulichung an, ich habe eine Klasse, die so aussieht:

public class Point {
    public final int row;
    public final int col;

    public Point(int row, int col) {
        this.row = row;
        this.col = col;
    }    

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (obj.getClass() != this.getClass()) return false;
        final Point other = (Point) obj;
        return this.row == other.row && this.col == other.col;
    }

    @Override
    public int hashCode() {
        return Objects.hash(row, col); 
    }
}

Und dann habe ich zwei schöne Bäche, die aussehen wie:

Stream<Point> streamA = Stream.of(new Point(2, 5), new Point(3, 1));
Stream<Point> streamB = Stream.of(new Point(7, 3), new Point(3, 1));

Angesichts der Tatsache, dass diese Streams 1 Punkt gemeinsam haben (nämlich Point(3, 1)), möchte ich, dass das Endergebnis wahr ist.

Die gewünschte Funktionalität kann wie folgt dargestellt werden:

public static boolean haveSomethingInCommon(Stream<Point> a, Stream<Point> b){
    //Code that compares a and b and returns true if they have at least 1 element in common
}

Antworten

1 YCF_L Nov 23 2020 at 14:37

Zunächst müssen Sie Ihre Streams in ein Set oder eine Liste konvertieren, um den berühmten Fehler nicht zu erhalten:

java.lang.IllegalStateException: stream has already been operated upon or closed

Und dann können Sie anyMatchwie folgt verwenden:

public static boolean haveSomethingInCommon(Stream<Coord> a, Stream<Coord> b) {
    Set<Coord> setA = a.collect(Collectors.toSet());
    Set<Coord> setB = b.collect(Collectors.toSet());

    return setA.stream().anyMatch(setB::contains);
}

Oder Sie können nur den bStream in ein Set konvertieren und Folgendes verwenden:

public static boolean haveSomethingInCommon(Stream<Coord> a, Stream<Coord> b) {
    Set<Coord> setB = b.collect(Collectors.toSet());
    return a.anyMatch(setB::contains);
}

Ich würde empfehlen, Set<Coord>statt Stream<Coord>als Parameter in Ihrer Methode.

public static boolean haveSomethingInCommon(Set<Coord> a, Set<Coord> b) {
    return a.stream().anyMatch(b::contains);
}
2 Naman Nov 23 2020 at 16:17

Ohne die beiden Streams unabhängig voneinander zu erfassen, können Sie gruppieren und identifizieren, ob einem Schlüssel mehrere Werte zugeordnet sind.

public static boolean haveSomethingInCommon(Stream<Coord> a, Stream<Coord> b) {
    return Stream.concat(a, b)
            .collect(Collectors.groupingBy(Function.identity()))
            .values().stream()
            .anyMatch(l -> l.size() > 1);
}

Wenn derselbe Stream zweimal oder öfter dasselbe Element haben kann , können Sie den zu verwendenden Code ändern -

Stream.concat(a.distinct(), b.distinct())
Kaplan Nov 23 2020 at 18:19

Es gibt eine Funktion disjoint in Collections :

public static boolean haveSomethingInCommon( Stream<Coord> a, Stream<Coord> b ) {
  return( ! Collections.disjoint( a.collect( toList() ), b.collect( toList() ) ) );
}