2016-05-26 9 views
8

Das Ermitteln einer Schnittmenge von zwei Streams oder das Ermitteln, ob ihre Kreuzung leer ist oder nicht, ist in Java im Allgemeinen nicht möglich, da Streams nur einmal verwendet werden können und die generische Lösung eine O(m*n) Komplexität aufweist .Ermitteln, ob Stream-Schnittmenge nicht leer ist

Wenn wir nichts über die Natur der zugrunde liegenden Lieferanten kennen, können wir mit höchstens einem Strom und einer Sammlung weg:

<T> boolean intersects(final Stream<T> c1, final Collection<T> c2) { 
    return c1.filter(c2::contains).findAny().isPresent(); 
} 

Doch was, wenn beide unsere Lieferanten bestellt vertreten Sammlungen sortiert mit dem gleichen Komparator (im einfachsten Fall zwei TreeSet s von Comparable s)? In diesem Fall hat die Lösung linear Komplexität (oder genauer O(m*n), siehe this Antwort).

Nun ist die Frage: kann die obige lineare Lösung implementiert werden nur Stream-API (i e mit zwei Ströme als Eingang..)?

+0

Fragen Sie, ob Sie die lineare Lösung implementieren können, wenn die Daten in den Streams geordnet sind? –

+4

Iterative Lösungen und Streams passen nicht zusammen, also ist das Beste, was Sie tun können, 'iterator()' in den Streams aufzurufen und weiter zu machen. – Holger

+0

@JimMischel Ja, genau – Bass

Antwort

7

Sie können nur den zweiten Strom in ein Set sammeln und fragen, ob ein Element des ersten Stroms in diesem Set enthalten ist:

<T> boolean intersects(final Stream<T> c1, final Stream<T> c2) { 
    return c1.anyMatch(c2.collect(Collectors.toSet())::contains); 
} 

macht das Set aus c1 ist linear in Bezug auf die Anzahl der Elemente darin, und contains ist eine konstante Zeit-Operation.

+0

Danke, das ist eine gute Lösung und beantwortet die Frage, da keine Einschränkungen hinsichtlich des Speicherbedarfs gesetzt wurden. Dennoch erfordert die ursprüngliche iterative Lösung (die einen der beiden Iteratoren unterstützt) keinen zusätzlichen Speicher, während der Stream-basierte dies tut. Ist es möglich, die gleiche Aufgabe in linearer Zeit zu lösen, ohne neue Kollektionen einzuführen? – Bass

+3

@Bass kurze Antwort: nein. Lange Antwort: Nein. Nicht ohne die Streams zurück zu Iteratoren zu konvertieren. –

+2

@Bass Und das Problem mit einem Iterator ist, dass Sie ein Element nicht einfach "sehen" können. Sie müssen es mit 'next()' konsumieren, so dass es viel schwieriger ist, nur einen der beiden Iteratoren weiterzuentwickeln. – Tunaki