【问题标题】:java data-structure to simulate a data treejava数据结构模拟数据树
【发布时间】:2010-11-18 16:06:06
【问题描述】:

我需要帮助来定义使用什么方法。我有一个 SOAP 响应给我一个 xml 文件。我最终需要在屏幕上显示 3 个相关列表。当您在第一个列表中选择一个项目时,相应的选项将出现在第二个列表中等等。我只对从 xml 流中提取数据后如何有效地组织数据感兴趣。这是一个xml sn-p:

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

所以,我会有一些类似的东西,manufacturer={"Acer", "Acer", "Acer","Samsung"}, model={"A1","A1", "A2", "E400"},平台={"Android","J2ME","Android","Android"}。

有趣的部分来了:我需要处理数据,以便可以使用它来显示 3 个列表。选择安卓后,宏碁和三星就可以使用了。如果选择 Acer,则型号 A1 和 A2 可用。所有列表都需要排序。目前我正在使用 Sax 将数据解析为对象向量,其中包含制造商、模型、平台字段。我能想到的只是一个类似于 TreeMap 的结构。任何建议,将不胜感激。

【问题讨论】:

    标签: java parsing data-structures map tree


    【解决方案1】:

    我不认为层次结构是你需要的。因为用户可以选择第一个平台或制造商。如果他选择第一个 Android,您想显示 3 台设备。如果他选择第一个 Acer,他将看到 2 个设备。

    所以,我的建议如下。

    1. 创建具有制造商、型号、平台属性的设备类。
    2. 创建一个包含所有这些设备的普通链表。
    3. 创建 2 个映射:manufaturerIndex 和 plarformIndex,如下所示:
      Map&lt;String, Collection&lt;Device&gt;&gt; manufacturerIndex;

    4. 遍历列表一次并填充所有索引映射。

    像这样:

    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
    }
    

    现在你可以使用数据结构了。

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

    注意这个数据结构是可扩展的。您可以随时添加任意数量的索引。

    【讨论】:

    • 我喜欢你的回答(这是我的另一个想法 :-)),所以 +1。但请学习正确格式化您的代码。我试着为你做,但显然有序列表和代码块不能很好地协同工作。
    • 我的用户在填写此信息之前将不得不跳过一系列环节,因此我可以保证他们选择的顺序是平台/制造商/型号。我将使用这个解决方案,因为其中大部分已经实现。谢谢。
    • 为了完整起见,我使用了来自 org.apache.commons.collections.map 的 MultiValueMap
    • 为了完整起见,我最后使用了来自 org.apache.commons.collections.map 的 MultiValueMap(此处示例:taypworm.com/node/81)。它允许重复键并返回任何键的值集合:key1=[v1, v2, v3]
    【解决方案2】:

    我只使用自定义对象的可排序集合,然后根据谓词过滤该集合。我使用Guava 来完成所有这些,但当然还有其他(通常更复杂)的方法来实现它。

    这是我的产品对象:

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

    现在我只需使用 TreeSet&lt;Product&gt; 并在其上应用视图。这是一个返回按模型过滤的实时视图的示例方法:

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

    像这样使用它:

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

    更新:我们可以更进一步,只使用一个集合,由链式谓词支持,而链式谓词又与视图支持的模型相关联。脑袋疼?看看这个:

    // 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 是一个由表单控制器返回的值支持的对象。每个谓词使用这个模型对象的一个​​字段来决定它是否适用。

    例如ModelPredicate 检查集合中的所有产品,以查看其型号是否在所选产品中。由于这使用了and 逻辑,因此您可以将其设为层次结构(如果制造商谓词返回 false,则永远不会调用模型和平台谓词)。

    【讨论】:

    • 我以前从未看过 Guava,但看起来 Google 非常重视填补 Sun/Oracle 留下的许多漏洞。我已经按照 AlexR 的建议实施了一个解决方案,所以他得到了复选标记。不过,感谢您向我介绍 Guava。
    • 谢谢。顺便说一下,看看我的更新:我已经为这个问题添加了一个更完整的解决方案。
    【解决方案3】:

    我使用嵌套地图来做类似的事情。使用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 ...
    

    【讨论】:

      猜你喜欢
      • 2010-10-30
      • 2010-10-30
      • 2013-11-03
      • 2013-12-20
      • 1970-01-01
      • 1970-01-01
      • 2016-09-13
      • 1970-01-01
      • 2011-05-18
      相关资源
      最近更新 更多