¿Cómo comprobar si dos corrientes están separadas?
Me gustaría comparar con las transmisiones y verificar si tienen 1 o más elementos en común (encontrar 1 es suficiente para dejar de buscar más). Quiero poder aplicar esto a Streams que contengan una clase personalizada.
Por ejemplo, digamos que tengo una clase que se parece a:
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);
}
}
Y luego tengo dos arroyos encantadores que se ven así:
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));
Dado que estas transmisiones tienen 1 punto en común (es decir, Point(3, 1)), me gustaría que el resultado final fuera cierto.
La funcionalidad deseada se puede representar como:
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
}
Respuestas
Primero que nada tienes que convertir tus Streams a un Set o List para no obtener el famoso error:
java.lang.IllegalStateException: stream has already been operated upon or closed
Y luego puedes usarlo anyMatchasí:
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);
}
O puede convertir solo la bsecuencia en un conjunto y usar:
public static boolean haveSomethingInCommon(Stream<Coord> a, Stream<Coord> b) {
Set<Coord> setB = b.collect(Collectors.toSet());
return a.anyMatch(setB::contains);
}
Recomendaría hacerlo en Set<Coord>lugar de Stream<Coord>como parámetro en su método.
public static boolean haveSomethingInCommon(Set<Coord> a, Set<Coord> b) {
return a.stream().anyMatch(b::contains);
}
Sin recopilar los dos flujos de forma independiente, puede agrupar e identificar si se asignan varios valores a cualquier clave.
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);
}
Si la misma secuencia puede tener el mismo elemento dos veces o más , puede cambiar el código para usar:
Stream.concat(a.distinct(), b.distinct())
hay una función disjoint en Collections :
public static boolean haveSomethingInCommon( Stream<Coord> a, Stream<Coord> b ) {
return( ! Collections.disjoint( a.collect( toList() ), b.collect( toList() ) ) );
}