2010-11-18 6 views
3

Ich brauche Hilfe bei der Definition des zu verwendenden Ansatzes. Ich habe eine SOAP-Antwort, die mir eine XML-Datei gibt. Ich muss am Ende 3 korrelierte Listen auf dem Bildschirm angezeigt werden. Wenn Sie ein Element in der ersten Liste auswählen, erscheinen die entsprechenden Auswahlmöglichkeiten in der zweiten Liste usw. Ich bin nur daran interessiert, wie die Daten effizient organisiert werden, nachdem sie aus dem XML-Stream extrahiert wurden. Hier ist ein XML-Schnipsel:Java-Datenstruktur zur Simulation eines Datenbaums

<device> 
    <manufacturer>Acer</manufacturer> 
    <model>A1</model> 
    <platform>Android</platform> 
</device> 
<device> 
    <manufacturer>Acer</manufacturer> 
    <model>A1</model> 
    <platform>J2ME</platform> 
</device> 
<device> 
    <manufacturer>Acer</manufacturer> 
    <model>A2</model> 
    <platform>Android</platform> 
</device> 
<device> 
    <manufacturer>Samsung</manufacturer> 
    <model>E400</model> 
    <platform>Android</platform> 
</device> 

So werde ich so etwas wie Hersteller haben = { "Acer", "Acer", "Acer", "Samsung"}, model = { "A1", "A1", "A2", "E400"}, Plattform = {"Android", "J2ME", "Android", "Android"}.

Hier kommt der spaßige Teil: Ich muss die Daten massieren, damit ich sie verwenden kann, um 3 Listen anzuzeigen. Nach der Auswahl von Android werden Acer und Samsung verfügbar. Wenn Acer ausgewählt ist, sind die Modelle A1 und A2 verfügbar. Alle Listen müssen sortiert werden. Zur Zeit verwende ich Sax, um die Daten in einen Vektor von Objekten zu analysieren, die Hersteller-, Modell- und Plattformfelder enthalten. Alles, woran ich denken kann, ist eine TreeMap-ähnliche Struktur. Irgendwelche Vorschläge würden geschätzt werden.

Antwort

4

Ich glaube nicht, dass hierarchische Struktur ist das, was Sie hier benötigen. Weil der Benutzer die erste Plattform oder den ersten Hersteller auswählen kann. Wenn er das erste Android auswählt, möchten Sie 3 Geräte anzeigen. Wenn er zuerst Acer wählt, sieht er 2 Geräte.

Also, mein Vorschlag ist das Folgende.

  1. Klasse erstellen Gerät mit Eigenschaften Hersteller, Modell, Plattform.
  2. erstellen Sie eine einfache verknüpfte Liste, die alle diese Geräte enthält.
  3. erstellen 2 Karten: manufaturerIndex und plarformIndex, die wie folgt aussehen:
    Map<String, Collection<Device>> manufacturerIndex;

  4. Iterate einmal über die Liste und alle Indizes Karten füllen.

So:

for(Device d : devices) { 
    Collection<Device> selected = manufacturerIndex.get(d.getManufacturer()); 
    if (selected == null) { 
     selected = new ArrayList<Device>(); 
     manufactuerIndex.put(d.getManufacturer(), selected); 
    } 
    selected.add(d); 
    // the same for the second index 
} 

Jetzt können Sie die Datenstruktur verwenden.

manufactuerIndex.get("Nokia") -> gibt alle Nokia Geräte zurück.

Beachten Sie, dass diese Datenstruktur erweiterbar ist. Sie können immer so viele Indizes hinzufügen, wie Sie möchten.

+0

Ich mag deine Antwort (es war meine andere Idee :-)), also +1 für das. Aber bitte lernen Sie, Ihren Code richtig zu formatieren. Ich habe versucht, es für dich zu tun, aber offenbar funktionieren geordnete Listen und Codeblöcke nicht gut zusammen. –

+0

Meine Benutzer müssen durch eine Reihe von Reifen springen, bevor Sie diese Informationen ausfüllen, damit ich garantieren kann, dass die Reihenfolge ihrer Entscheidungen Plattform/Hersteller/Modell ist. Ich werde diese Lösung verwenden, da die meisten davon bereits implementiert wurden. Vielen Dank. – alex

+0

Der Vollständigkeit halber habe ich eine MultiValueMap von org.apache.commons.collections.map verwendet – alex

1

Ich verwende verschachtelte Karten für so etwas. Verwenden Sie TreeMap sortierten Ergebnisse zu erhalten:

TreeMap<String, TreeMap<String, Model> manufacturerMap; 

TreeMap<String, Model> models = manufacturerMap.get(name); 
if(models == null) { 
    models = new TreeMap<String, Model>(); 
    manufacturerMap.put(name. models); 
} 

... etc ... 
2

Ich würde nur eine sortierbare Sammlung von benutzerdefinierten Objekten verwenden und dann diese Sammlung basierend auf Prädikaten filtern. Ich benutze Guava für all dies, aber es gibt natürlich andere (in der Regel kompliziertere) Möglichkeiten, dies zu implementieren.

Hier ist mein Produktobjekt:

public class Product implements Comparable<Product>{ 

    private final String manufacturer; 
    private final String model; 
    private final String platform; 

    public Product(final String manufacturer, 
     final String model, 
     final String platform){ 
     this.manufacturer = manufacturer; 
     this.model = model; 
     this.platform = platform; 
    } 

    public String getManufacturer(){ 
     return manufacturer; 
    } 

    public String getModel(){ 
     return model; 
    } 

    public String getPlatform(){ 
     return platform; 
    } 

    @Override 
    public int hashCode(){ 
     return Objects.hashCode(manufacturer, model, platform); 
    } 

    @Override 
    public boolean equals(final Object obj){ 
     if(obj instanceof Product){ 
      final Product other = (Product) obj; 
      return Objects.equal(manufacturer, other.manufacturer) 
       && Objects.equal(model, other.model) 
       && Objects.equal(platform, other.platform); 
     } 
     return false; 
    } 

    @Override 
    public int compareTo(final Product o){ 
     return ComparisonChain 
      .start() 
      .compare(manufacturer, o.manufacturer) 
      .compare(model, o.model) 
      .compare(platform, o.platform) 
      .result(); 
    } 

} 

Jetzt würde ich nutze einfach ein TreeSet<Product> und anwenden Blick darauf.Hier ist ein Beispiel-Methode, die eine Live-Ansicht zurück, das nach Modell gefiltert wird:

public static Collection<Product> filterByModel(
    final Collection<Product> products, 
    final String model){ 
    return Collections2.filter(products, new Predicate<Product>(){ 

     @Override 
     public boolean apply(final Product product){ 
      return product.getModel().equals(model); 
     } 
    }); 
} 

es wie folgt verwendet:

Collection<Product> products = new TreeSet<Product>(); 
// add some products 
Collection<Product> filtered = filterByModel(products, "A1"); 

Update: nehmen wir es noch weiter, nur eine Sammlung verwenden, unterstützt durch verkettete Prädikate, die wiederum an ein Modell gebunden sind, das von Ihrer Ansicht unterstützt wird. Gehirn tut weh? Check this out:

// this is the collection you sent to your view 
final Collection<Product> visibleProducts = 
    Collections2.filter(products, Predicates.and(Arrays.asList(
     new ManufacturerPredicate(yourViewModel), 
     new ModelPredicate(yourViewModel), 
     new PlatformModel(yourViewModel))) 
); 

yourViewModel ist ein Objekt, das durch die Werte zurückgegeben von dem Formular-Controller unterstützt wird. Jedes Prädikat verwendet ein Feld dieses Modellobjekts, um zu entscheiden, ob es zutrifft oder nicht.

z.B. Die ModelPredicate prüft alle Produkte in der Sammlung, um zu sehen, ob ihr Modell zu den ausgewählten gehört. Da dies die Logik and verwendet, können Sie eine hierarchische Struktur erstellen (wenn das Prädikat des Herstellers false zurückgibt, werden die Modell- und Plattformprädikate nie aufgerufen).

+0

ausgezeichnet, TY für das Posten dieses – Pete

+0

Ich schaute nie Guava vorher an, aber es sieht wie Google sehr ernst mit ein Viele Löcher von Sun/Oracle. Ich implementierte bereits eine Lösung, die AlexR vorgeschlagen hatte, und bekam das Häkchen. Aber danke, dass Sie mich in Guava vorgestellt haben. – alex

+0

Danke. By the way, überprüfen Sie mein Update: Ich habe eine viel vollständigere Lösung für das Problem hinzugefügt. –