简体   繁体   English

java数据结构来模拟数据树

[英]java data-structure to simulate a data tree

I need help defining what approach to use. 我需要帮助定义使用的方法。 I have a SOAP response giving me an xml file. 我有一个SOAP响应给我一个xml文件。 I need to end-up with 3 correlated lists displayed on screen. 我需要最终在屏幕上显示3个相关列表。 When you select one item on the first list, the corresponding choices will appear on the second list etc. I am only interested on how to organize efficiently the data after it is extracted from the xml stream. 当您在第一个列表中选择一个项目时,相应的选项将出现在第二个列表等上。我只对如何在从xml流中提取数据后有效组织数据感兴趣。 Here's an xml snippet: 这是一个xml片段:

<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, I will have something like manufacturer={"Acer", "Acer", "Acer","Samsung"}, model={"A1","A1", "A2", "E400"}, platform={"Android","J2ME","Android","Android"}. 所以,我会有像manufacturer = {“Acer”,“Acer”,“Acer”,“Samsung”},model = {“A1”,“A1”,“A2”,“E400”},platform = { “机器人”, “J2ME”, “机器人”, “机器人”}。

Here comes the fun part: I need to massage the data so that I can use it to display 3 lists. 有趣的是:我需要按摩数据,以便我可以使用它来显示3个列表。 After selecting Android, Acer and Samsung become available. 选择Android后,Acer和三星即可上市。 If Acer is selected, then model A1 and A2 are available. 如果选择Acer,则可以使用型号A1和A2。 All lists need to be sorted. 所有列表都需要排序。 Currently I'm using Sax to parse the data into a vector of objects, containing manufacturer, model, platform fields. 目前我正在使用Sax将数据解析为对象向量,包含制造商,模型,平台字段。 All I can think of is a TreeMap like structure. 我能想到的只是一个类似TreeMap的结构。 Any suggestions would be appreciated. 任何建议,将不胜感激。

I do not think that hierarchical structure is what you need here. 我认为这里不需要层次结构。 Because user may select first platform or manufacturer. 因为用户可以选择第一平台或制造商。 If he selects first Android you want to show 3 devices. 如果他选择第一个Android,则要显示3个设备。 If he selects first Acer he will see 2 devices. 如果他选择第一个宏基,他会看到2个设备。

So, my suggesting is the following. 所以,我的建议如下。

  1. create class Device with properties manufacturer, model, platform. 使用属性制造商,型号,平台创建类设备。
  2. create a plain linked list that contains all these devices. 创建包含所有这些设备的纯链接列表。
  3. Create 2 maps: manufaturerIndex and plarformIndex that look like: 创建2个map:manufaturerIndex和plarformIndex,如下所示:
    Map<String, Collection<Device>> manufacturerIndex;

  4. Iterate once over the list and populate all indexes maps. 在列表上迭代一次并填充所有索引映射。

Like this: 像这样:

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
}

Now you can use the data structure. 现在您可以使用数据结构。

manufactuerIndex.get("Nokia") -> returns all Nokia devices. manufactuerIndex.get("Nokia") - >返回所有诺基亚设备。

Pay attention that this data structure is extendable. 注意这个数据结构是可扩展的。 You can always add as many indexes as you want. 您始终可以根据需要添加任意数量的索引。

I'd just use a sortable collection of custom objects and then filter that collection based on predicates. 我只使用可排序的自定义对象集合,然后根据谓词过滤该集合。 I am using Guava for all of this, but there are of course other (usually more complicated) ways to implement this. 我正在使用Guava来实现这一切,但当然还有其他(通常更复杂的)方法来实现它。

Here's my Product Object: 这是我的产品对象:

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();
    }

}

Now I'd just use a TreeSet<Product> and apply views on it. 现在我只使用TreeSet<Product>并对其应用视图。 Here's a sample method that returns a live view that is filtered by model: 这是一个示例方法,它返回按模型过滤的实时视图:

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);
        }
    });
}

Use it like this: 像这样使用它:

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

Update: We can take it even further, using only one collection, backed by chained predicates that are in turn tied to a model backed by your view. 更新:我们可以更进一步,只使用一个集合,由链式谓词支持,而这些谓词依次绑定到视图支持的模型。 Brain hurts? 大脑疼吗? 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 is an object that is backed by the values returned from your form controller. yourViewModel是一个由表单控制器返回的值支持的对象。 Each predicate uses a field of this model object to decide whether it applies or not. 每个谓词都使用此模型对象的字段来决定它是否适用。

eg The ModelPredicate checks all products in the collection to see whether their model is among the selected ones. 例如, ModelPredicate检查集合中的所有产品,以查看其模型是否属于所选产品。 Since this uses and logic, you can make it a hierarchic structure (if the manufacturer predicate returns false, the model and platform predicates are never called). 由于这是使用and逻辑,您可以使它成为一个层次结构(如果制造商谓词返回false,则永远不会调用模型和平台谓词)。

I use nested maps for something like that. 我使用嵌套地图做类似的事情。 Use TreeMap to get sorted results: 使用TreeMap获取排序结果:

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 ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM