2016-02-04 9 views
9

Also wenn ich ein Name Objekt und haben eine ArrayList vom Typ Name (names), und ich möchte wissen, ob meine Liste der Namen enthält ein gegebenes Name Objekt (n), konnte ich es zwei tun Wege:Java enthält vs AnyMatch Verhalten

boolean exists = names.contains(n); 

oder

boolean exists - names.stream().anyMatch(x -> x.equals(n)); 

ich erwäge, wenn diese zwei gleich verhalten würde und dachte dann über das, was passiert, wenn nzugewiesen wurde?

Für enthält, wie ich verstehe, wenn das Argument null ist, dann gibt es true zurück, wenn die Liste null enthält. Wie würde ich dies erreichen anyMatch - wäre es mit Objects.equals(x, n)?

Wenn das funktioniert, welcher Ansatz ist effizienter - ist es anyMatch wie es Faulheit und Parallelität nutzen kann?

+0

Was ist 'name' Typ? – Tunaki

+1

Wenn 'Namen' tatsächlich eine' ArrayList' ist, würde ich vermuten, dass die Leistung ähnlich wäre. Aber wenn es so etwas wie ein 'HashSet' ist, dann wäre ein' contains'-Aufruf mit ziemlicher Sicherheit effizienter (da er nicht tatsächlich die Elemente durchlaufen muss). –

+0

@JoachimSauer Er * sagte *, dass es eine 'ArrayList' ist. Es ist zumindest vernünftig anzunehmen, dass dies wahr ist. – Marco13

Antwort

10

Das Problem mit dem Strom-basierte Version ist, dass wenn die Sammlung (und deren Strom so) null Elemente enthält, dann wird das Prädikat ein NullPointerException werfen, wenn er versucht equals auf dieser null Objekt aufzurufen.

Dies könnte mit

boolean exists = names.stream().anyMatch(x -> Objects.equals(x, n)); 

vermieden Aber es gibt keinen praktischen Vorteil für die Stream-basierte Lösung in diesem Fall zu erwarten. Parallelität könnte einen Vorteil für wirklich große Listen bringen, aber man sollte nicht zufällig werfen einige parallel() hier und da unter der Annahme, dass es kann Dinge schneller machen. Zuerst sollten Sie die tatsächlichen Engpässe klar identifizieren.

Und in Bezug auf Lesbarkeit würde ich hier die erste, klassische Lösung bevorzugen. Wenn Sie überprüfen wollen, ob die Liste der names.contains(aParticularValue), sollten Sie dies tun - es liest sich nur wie Prosa und macht die Absicht klar.

EDIT

Ein weiterer Vorteil der contains Ansatz wurde in den Kommentaren und in der anderen Antwort erwähnt, und das kann sich lohnen, hier zu erwähnen: Wenn die Art der names Sammlung später geändert wird, für B. ein HashSet, dann erhalten Sie die schnellere contains -check (mit O (1) anstelle von O (n)) kostenlos - ohne Änderung eines anderen Teils des Codes. Die strombasierte Lösung müsste dann immer noch über alle Elemente iterieren, und dies könnte eine deutlich geringere Leistung haben.

+0

auch: * wenn * Leistung relevant wird, dann in einen anderen Datentyp Schalt ist eine Art und Weise einfache Art und Weise der Leistung zu verbessern, als es zu werfen Parallelität ('LinkedHashSet' oder ähnlich, wenn der Auftrag beibehalten werden muss). –

1

Sie sollten das gleiche Ergebnis liefern, wenn hashCode() und equals() in angemessener Weise geschrieben werden.

Aber die Leistung kann komplett anders sein. Für Listen ist es nicht so wichtig, aber für HashSet wird hashCode() verwendet, um das Element zu finden, und es wird (höchstwahrscheinlich) in konstanter Zeit durchgeführt.Während mit der zweiten Lösung wird es über alle Elemente Schleife und rufen Sie eine Funktion, so wird in linearer Zeit erfolgen.

Wenn n null ist, ist eigentlich keine Rolle wie in der Regel equals() Methoden sind bekannt, null Argumente.

+1

Sie haben recht, dass jede 'equals'-Methode überprüfen sollte, ob ihr * Argument * 'null' ist. Aber hier könnte das Prädikat versuchen, die 'equals'-Methode für ein 'null'-Objekt aufzurufen, das zu einem NPE führt – Marco13