2016-05-05 4 views
3

Kontinent ist ein zusammengesetztes Objekt. Die Struktur ist:Java Optionale Verwendung für Multi-Map

Continent 
--Country 
----State 
------Town 

so in dieser Notation:

town= Optional.of(continent) 
      .map(Continent::getCountry) 
      .map(Country::getState) 
      .map(State::getTown) 
      .orElse(null); 

dies funktioniert gut, aber wenn ich versuche, eine allgemeine Mapper zu schreiben,

public static <T, R> T getFromMapping(R source, 
             T defaultValue, 
             Function<?,?>... functions) { 
     Optional sourceWrapper = Optional.ofNullable(source); 
     for (Function function : functions) { 
     sourceWrapper.map(function); 
     } 
    return (T) sourceWrapper.orElse(defaultValue); 
    } 

und rufen Sie es von

portfolio = getFromMapping(continent, null, 
      ((Function<Continent, Country>) Continent::getCountry) 
      ((Function<Country, State>) Country::getState), 
      ((Function<State, Town>) State::getTown)); 

es kompilieren einfach gut aber arbeite nicht. Der Mapper springt zum zweiten Schritt nach und sagt, Kontinent könne nicht ins Land werfen, warum? sollte es beim Mapping keine Besetzung geben, wie kann man es reparieren?

+2

Sie können Ihre "T" und "R" tauschen, um Verwechslungen zu vermeiden. 'java.util.function' hat die lockere Namenskonvention, dass' T' und 'U' Eingaben sind und' R' ein Rückgabewert ist. Sie bauen im Wesentlichen eine 'Funktion ' –

+0

Vorschlag: Wenn Sie Varianten von 'getFromMapping' mit festen Nummern von Funktionen erstellen, haben Sie eine typsichere Lösung und brauchen die Argumente nicht mehr zu werfen. – stholzm

+0

@HankD Danke Hank, ich habe die Schnittstelle ~ –

Antwort

5

Optional#map modifiziert sich nicht selbst, sondern gibt stattdessen einen neuen Optional zurück, so dass immer noch Ihren Kontinent enthält. Sie sollten die Variable in der for-Schleife neu zuweisen:

sourceWrapper = sourceWrapper.map(function); 
+0

Danke !! Ich hab es geschafft –