[英]Using Java Generics to recurse over an object with a list of objects (each with another list of objects)
我有三个接口:
public interface Combinable<V> {
V add(V other);
}
public interface Sublistable<V> {
boolean hasSublist();
List<V> getSublist();
void setSublist(List<V> sublist);
}
public interface HasUniqueIdentifier {
String getUniqueIdentifier();
}
和4个实现部分或全部这些接口的类:
public class Grandparent implements HasUniqueIdentifier,
Sublistable<Parent>,
Combinable<Grandparent>
{ List<Parent> sublist; ... }
public class Parent implements HasUniqueIdentifier,
Sublistable<Child>,
Combinable<Parent>
{ List<Child> sublist; ... }
public class Child implements HasUniqueIdentifier,
Sublistable<Grandchild>,
Combinable<Child>
{ List<Grandchild> sublist; ... }
public class Grandchild implements HasUniqueIdentifier,
Combinable<Grandchild>
{ }
我想有一个执行以下操作的通用方法:
public <V, T extends HasUniqueIdentifier & Combinable<T> & Sublistable<V>>
List<T> combine(List<T> items) {
Multimap<String, T> similarItemMap = HashMultimap.create();
for (T item: items) {
similarItemMap.put(item.getUniqueIdentifier(), item);
}
List<T> output = new ArrayList<T>();
for (Collection<T> similarCollection : similarItemMap.asMap().values()) {
List<T> similarItems = Lists.newArrayList(similarCollection);
T source = similarItems.get(0);
for (int i = 0; i < similarItems.size(); i++) {
source = source.add(similarItems.get(i));
}
output.add(source);
}
for (T item : output) {
if (item.hasSublist()) {
item.setSublist(combine(item.getSublist));
}
}
return output;
}
意识到这可能会创建一个无限循环(除非底层类--Grandchild - 实现Sublistable并设置hasSublist() { return false; }
或者其他东西),以及这个方法对泛型有点疯狂的事实,我不得不问:有什么方法可以重写一下,以便我可以这样调用方法:
combine(listOfGrandparents)
或者我应该放弃这种方法并尝试以更好的方式重构它?
编辑:为了更好地解释我正在尝试做什么,我有一个类型为A
的对象列表。 每个对象a
都有一个B
类对象列表。 每个对象b
都有一个C
类型的对象列表,依此类推,直到最终类型T
(对于某些不同级别的T
)不再有子列表。
对于“合并”或“组合”方法,每种类型基本上都需要做三件事:
item.getUniqueIdentifier()
方法将所有“like”项目收集到容器中 source.add(other)
方法将所有类似项目合并为一个项目 由于每个项目的行为如此相似,如果我可以使用单个方法而不必拥有n
方法,每种类型一个,那将是很好的。 不幸的是,由于没有任何类型保证是相同的(除了实现上面的一些或所有给定接口之外),创建通用方法证明是困难的。 有没有办法做到这一点,我错过了?
public <V extends HasUniqueIdentifier & Combinable<V>, T extends HasUniqueIdentifier & Combinable<T>> List<T> combine(List<T> items) { Multimap<String, T> similarItemMap = HashMultimap.create(); for (T item: items) { similarItemMap.put(item.getUniqueIdentifier(), item); } List<T> output = new ArrayList<T>(); for (Collection<T> similarCollection : similarItemMap.asMap().values()) { List<T> similarItems = Lists.newArrayList(similarCollection); T source = similarItems.get(0); for (int i = 0; i < similarItems.size(); i++) { source = source.add(similarItems.get(i)); } output.add(source); } for (T item : output) { if (item instanceof Sublistable<?>) { @SuppressWarnings("unchecked") Sublistable<V> sublistableItem = ((Sublistable<V>)sublistableItem); if (sublistableItem.hasSublist()) { sublistableItem.setSublist(combine(sublistableItem.getSublist)); } } } return output; }
不幸的是,这种方法需要@SupressWarnings
和instanceof
,如果可能的话我想避免。 但是,我还没有找到任何其他东西。
鉴于GrandChild implements Sublistable<Void>
,你的第一个解决方案很好。 树更加统一,并且更容易递归处理。 您可能还希望有一个合并的interface Node<T,V> extends HasUniqueIdentifier, Combinable<T>, Sublistable<V>{}
如果您不希望GrandChild implements Sublistable
,那么您的第二个解决方案也没问题。 测试标记接口的单个instanceof
不是罪。 代码可以重写为
public <T extends HasUniqueIdentifier & Combinable<T>>
List<T> combine(List<T> items)
{
...
List<T> output = new ArrayList<T>();
...
for (T item : output) {
if (item instanceof Sublistable<?>)
combineSublist((Sublistable<?>)item);
return output;
}
private <V> void combineSublist(Sublistable<V> sublistableItem)
{
if (sublistableItem.hasSublist()) {
sublistableItem.setSublist(combine(sublistableItem.getSublist));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.