2016-09-21 4 views
0

sammeln Ich bekomme "Inkompatible Typen, erforderlich: CopyOnWriteArrayList, gefunden: Object" mit den folgenden. Ich verwende IntelliJ 2016.1.1.Wie man einen Stream in eine CopyOnWriteArrayList

+1

Tipp: Vielleicht brauchst du irgendwo einen Typhint, wie 'Collections '. toCollection() 'oder so ähnlich. Und jetzt die Idee, warum das abgelehnt wurde. Hat meinen Teil, um es zu beheben. – GhostCat

+0

Wird nicht helfen. Hier sind einige weitere Charaktere. – Seppo420

+0

Kannst du plz setzen, was deine Felder variabel sind? –

Antwort

1

Es scheint, dass Ihre Felder Objekt nicht vom Typ Foo ist, sonst sollte es Arbeit finden unten arbeiten Code.

import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.CopyOnWriteArrayList; 
import java.util.stream.Collectors; 

public class Foo { 


    private String name; 

    Foo(String name){ 

     this.name=name; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @Override 
    public String toString() { 
     return "Foo [name=" + name + "]"; 
    } 

    public static void main(String[] args) { 
     List<Foo> fields = new ArrayList<>(); 
     fields.add(new Foo("aa")); 
     fields.add(new Foo("bb")); 
     CopyOnWriteArrayList<Foo> l = fields.stream().distinct().collect(Collectors.toCollection(CopyOnWriteArrayList::new)); 

     System.out.println("l"+l); 
    } 


} 

PS: Wenn Ihre Felder dann diese geben Fehler wird auch allgemeine Nicht ist

1

Das Problem ist, dass fields eine unangemessene Art hat höchstwahrscheinlich eine rohe Art hat, die die verwandeln Generische Aufrufe der Stream-Kette in ungeprüfte Operationen, die ihren gelöschten Typ zurückgeben, der Object für den Terminal-Aufruf collect lautet.

die richtige Art verwenden, funktioniert dies ohne Probleme, das heißt

List<String> fields=Arrays.asList("foo", "bar", "baz", "foo"); 
CopyOnWriteArrayList<String> l = 
    fields.stream() 
      .distinct() 
      .collect(Collectors.toCollection(CopyOnWriteArrayList::new)); 

funktioniert. Beachten Sie aber, dass das Erstellen einer CopyOnWriteArrayList auf diese Weise ziemlich teuer ist, wie der Name "copy on write" bereits andeutet. Das Kopieren des gesamten Inhalts bei jeder Einfügung führt zu einer quadratischen Zeitkomplexität.

Die Lösung besteht darin, in einer temporären Sammlung zu sammeln, die besser für inkrementelles Bauen geeignet ist, bevor sie in den gewünschten Zieltyp konvertiert wird. Dieser Kopierschritt könnte wie Overhead aussehen, aber es ist linear Overhead, verglichen mit der quadratischen Komplexität des Sammelns direkt in die CopyOnWriteArrayList.

CopyOnWriteArrayList<String> l = 
    fields.stream() 
      .distinct() 
      .collect(Collectors.collectingAndThen(
           Collectors.toList(), CopyOnWriteArrayList::new)); 

Beachten Sie, dass in diesem speziellen Fall, baut distinct implizit eine Set hinter den Kulissen, so können wir die Leistung durch den Bau der Set explizit anstelle des temporären List und entfernen Sie den distinct Schritt verbessern:

CopyOnWriteArrayList<String> l = 
    fields.stream() 
      .collect(Collectors.collectingAndThen(
           Collectors.toCollection(LinkedHashSet::new), 
           CopyOnWriteArrayList::new)); 

was zu der Schlussfolgerung führt, dass wir für diesen spezifischen Anwendungsfall alles einfacher und potentiell noch effizienter haben können:

CopyOnWriteArrayList<String> l = new CopyOnWriteArrayList<>(new LinkedHashSet<>(fields)); 
Verwandte Themen