Wie überprüfe ich, ob zwei Streams nicht verbunden sind?
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
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 anyMatch
wie 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 b
Stream 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);
}
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())
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() ) ) );
}