我需要帮助定义使用的方法。我有一个SOAP响应给我一个xml文件。我需要最终在屏幕上显示3个相关列表。当您在第一个列表中选择一个项目时,相应的选项将出现在第二个列表等上。我只对如何在从xml流中提取数据后有效组织数据感兴趣。这是一个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>
所以,我会有像manufacturer = {“Acer”,“Acer”,“Acer”,“Samsung”},model = {“A1”,“A1”,“A2”,“E400”},平台= { “机器人”, “J2ME”, “机器人”, “机器人”}。
这是有趣的部分:我需要按摩数据,以便我可以使用它来显示3个列表。选择Android后,Acer和三星即可上市。如果选择Acer,则可以使用型号A1和A2。所有列表都需要排序。目前我正在使用Sax将数据解析为对象向量,包含制造商,模型,平台字段。我能想到的只是一个类似TreeMap的结构。任何建议,将不胜感激。
答案 0 :(得分:4)
我认为这里不需要层次结构。因为用户可以选择第一平台或制造商。如果他选择第一个Android,则要显示3个设备。如果他选择第一个宏基,他会看到2个设备。
所以,我的建议如下。
创建2个地图:manufaturerIndex和plarformIndex,如下所示:
Map<String, Collection<Device>> manufacturerIndex;
在列表上迭代一次并填充所有索引映射。
像这样:
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")
- &gt;返回所有诺基亚设备。
请注意此数据结构是可扩展的。您始终可以根据需要添加任意数量的索引。
答案 1 :(得分: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<Product>
并对其应用视图。这是一个示例方法,它返回按模型过滤的实时视图:
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
是一个由表单控制器返回的值支持的对象。每个谓词都使用此模型对象的字段来决定它是否适用。
e.g。 ModelPredicate
检查集合中的所有产品,以查看其模型是否属于所选产品。由于这使用and
逻辑,因此可以使其成为层次结构(如果制造商谓词返回false,则永远不会调用模型和平台谓词)。
答案 2 :(得分:1)
我使用嵌套地图做类似的事情。使用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 ...