2014-01-24 13 views
24

Ich habe den folgenden Code:Strom und die deutliche Operation

class C 
{ 
    String n; 

    C(String n) 
    { 
     this.n = n; 
    } 

    public String getN() { return n; } 

    @Override 
    public boolean equals(Object obj) 
    { 
     return this.getN().equals(((C)obj).getN()); 
    } 
} 

List<C> cc = Arrays.asList(new C("ONE"), new C("TWO"), new C("ONE")); 

System.out.println(cc.parallelStream().distinct().count()); 

aber ich verstehe nicht, warum distinct kehrt 3 und 2 nicht

+3

Aha, du bist mit Java 8. Versuchen experimentieren überschreibt auch 'hashCode()' in der Klasse 'C'. Wenn zwei C-Objekte gleich sind, müssen ihre Hash-Codes gleich sein. – Jesper

+1

Setzen Sie einen Haltepunkt innerhalb des überlagerten 'equals' und sehen Sie, ob' distinct' es betrachtet. –

+0

@Jesper, ich sah keine Sorge um 'Hashcode' in Dokumenten unter http://download.java.net/jdk8/docs/api/java/util/stream/Stream.html#Distinct-- –

Antwort

34

Sie müssen auch die hashCode Methode in der Klasse außer Kraft zu setzen C . Zum Beispiel:

@Override 
public int hashCode() { 
    return n.hashCode(); 
} 

Wenn zwei C Objekte gleich sind, ihre hashCode Methoden müssen den gleichen Wert zurück.

Die API-Dokumentation für Schnittstelle Stream erwähnt dies nicht, aber es ist bekannt, dass Sie, wenn Sie equals außer Kraft setzen, auch hashCode überschreiben sollten. Die API-Dokumentation für Object.equals() erwähnt dies:

Beachten Sie, dass es in der Regel notwendig ist, die hashCode Methode außer Kraft zu setzen, wenn diese Methode außer Kraft gesetzt wird, um den allgemeinen Auftrag für die hashCode Methode zu halten, die besagt, dass gleiche Objekte haben müssen gleiche Hash-Codes.

Offenbar Stream.distinct() in der Tat den Hash-Code der Objekte verwendet, denn wenn man es umsetzen, wie ich oben zeigte, können Sie das erwartete Ergebnis: 2.