2016-08-08 44 views
-1

Also hier ist das Problem. Ich habe drei Klassen wie folgt:Java8 Sammeln von Daten aus 2 verschiedenen Objektströmen zu einer sortierten Liste von 3rd Objekt

class ObjectClassA 
{ 
    private final long id; 
    private final String name; 
    private final boolean isReadOnly; 
    //<some more fields> 

    long getId() 
    { 
     return this.id; 
    } 

    String getName() 
    { 
     return this.name; 
    } 

    boolean isReadOnly() 
    { 
     return this.isReadOnly; 
    } 
} 

class ObjectClassB 
{ 
    private final long id; 
    private final String location; 
    private final boolean isReadOnly; 
    //<some more fields> 

    long getId() 
    { 
     return this.id; 
    } 

    String getLocation() 
    { 
     return this.location; 
    } 

    boolean isReadOnly() 
    { 
     return this.isReadOnly; 
    } 
} 

und

class ObjectClassC 
{ 
    private final String location; 
    private final boolean isReadOnly; 
    private final String location; 

    String getName() 
    { 
     return this.name; 
    } 

    boolean isReadOnly() 
    { 
     return this.isReadOnly; 
    } 

    String getLocation() 
    { 
     return this.location; 
    } 
} 

Ich habe 2 Karten -

Map<Id,ObjectClassA> mapObjectClassA 

und

Map<Id,ObjectClassB> mapObjectClassB 

Beide Karten sind von der gleichen Größe . Die ID-Schlüssel sind beiden Karten gemeinsam. Ziel ist es entweder über Karten iterieren List<ObjectClassC> Objekte eine sortierte (von ObjectClassC.name) zu schaffen, so dass:

ObjectClassC.name = ObjectClassA.name 
ObjectClassC.isReadOnly = ObjectClassA.isReadOnly || ObjectClassB.isReadOnly 
ObjectClassC.location = ObjectClassB.location 

Das ist die Logik, die ich jetzt habe, ist wie folgt:

final List<ObjectClassC> list = 
mapObjectClassA.values() 
       .stream() 
       .map(a -> { 
        new ObjectClassC(a.getName(), 
            a.isReadOnly() || mapObjectClassB.get(a.getId).isReadOnly(), 
            mapObjectClassB.get(a.getId).getLocation()) 
       }) 
       .sorted(Comparator.comparing(ObjectClassC::getName)) 
       .collect(Collectors.<ObjectClassC> toList()); 

Meine Mapping und Sammlung funktionieren gut, aber ich bekomme keine sortierte Sammlung von ObjectClassC Objekten. Könnte jemand bitte darauf hinweisen, wo ich falsch liege?

+1

Können Sie eine einfache Arbeit [MCVE] posten? Die 'sortierte' Operation sollte nach Namen sortiert werden. Welche Ausgabe erhalten Sie mit einer Beispieleingabe? – Tunaki

+1

Es gibt einige Tippfehler in Ihrem Code. Missing ')' am Ende der '.sorted' Zeile; no '()' auf 'a.getId'; zusätzliche Klammern um den 'neuen ObjektClassC'-Teil. Es wäre wirklich besser zu kopieren und einzufügen. –

+0

Sie können in 'ObjectClassC' nicht zwei Felder namens' location' haben. – Andreas

Antwort

0

Nicht so schön, aber funktioniert.

public class MapMerge_38837365 { 

    public static void main(String[] args) { 
     Map<Integer, A> as = new HashMap(); 
     as.put(1, new A("Anna")); 
     as.put(2, new A("Maria")); 
     as.put(3, new A("Eva")); 

     Map<Integer, B> bs = new HashMap(); 
     bs.put(1, new B("Adam")); 
     bs.put(2, new B("Edward")); 
     bs.put(3, new B("Jon")); 

     Stream.concat(
       as.entrySet().stream(), 
       bs.entrySet().stream() 
     ).collect(Collectors.groupingBy(Map.Entry::getKey)) 
       .entrySet().stream() 
       .map(e -> e.getValue()) 
       .map(e -> { 
        if (e.get(0).getValue() instanceof A) 
         return new AB((A) e.get(0).getValue(), (B) e.get(1).getValue()); 
        return new AB((A) e.get(1).getValue(), (B) e.get(0).getValue()); 
       }) 
       .map(ab -> new C(ab.a.name+" " +ab.b.name)) 
       .forEach(System.out::println); 
    } 
} 

"Die hohe Magie" geschieht in Stream.concat dann groupingBy. In diesen zwei Zeilen erzeugen wir einen Strom aller Einträge von beiden Karten. Dann gruppieren wir sie nach Schlüssel zu Karte. Elemente mit demselben Schlüssel (ID) werden zu einem List<Object>. Im nächsten Schritt erstellen Sie einen neuen Stream aus der Gruppierungskarte entrySet().stream().

Dann extrahieren wir Werte - Einträge mit dem gleichen Id>map(e -> e.getValue()).

Der nächste Schritt besteht darin, AB Objekte zu bauen und könnte weggelassen werden, aber ich möchte Typ prüfen und in eine andere Funktion umwandeln. Jetzt haben wir Pseudo-Paar AB, das ist sehr schön Kandidat für erstellen C Klasse map(ab -> new C(ab.a.name+" " +ab.b.name)).

Klassen A, B, C und AB:

class A { 

    final String name; 

    A(String name) { 
     this.name = name; 
    } 

    @Override 
    public String toString() { 
     return "A{" + 
       "name='" + name + '\'' + 
       '}'; 
    } 
} 

class B { 

    final String name; 

    B(String name) { 
     this.name = name; 
    } 

    @Override 
    public String toString() { 
     return "B{" + 
       "name='" + name + '\'' + 
       '}'; 
    } 
} 

class C { 

    final String name; 

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

    @Override 
    public String toString() { 
     return "C{" + 
       "name='" + name + '\'' + 
       '}'; 
    } 
} 

class AB { 

    final A a; 
    final B b; 

    AB(A a, B b) { 
     this.a = a; 
     this.b = b; 
    } 

    @Override 
    public String toString() { 
     return "AB{" + 
       "a=" + a + 
       ", b=" + b + 
       '}'; 
    } 
}