使用Java Generics通过一个对象列表(每个对象具有另一个对象列表)来递归对象

时间:2013-03-06 07:38:55

标签: java generics

我有三个界面:

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

意识到这可能会创建一个无限循环(除非底层类 - 孙子 - 实现了Sublistable并设置hasSublist() { return false; },或者其他东西),以及这种方法对泛型有点疯狂的事实,我不得不问:有什么方法可以重写一下,以便我可以这样调用方法:

combine(listOfGrandparents)

或者我应该放弃这种方法并尝试以更好的方式重构它?


修改 为了更好地解释我尝试做的是什么,我有一个A类型的对象列表。每个对象a都有一个B类型的对象列表。每个对象b都有C类型的对象列表,依此类推,直到最终输入T(对于某些不同级别的T)并不具备一个子列表了。

每种类型基本上都需要为&#34;合并&#34;或&#34;结合&#34;方法:

  1. 收集所有&#34;喜欢&#34;使用item.getUniqueIdentifier()方法
  2. 将项目放入容器中
  3. 使用source.add(other)方法
  4. 将所有相似项目合并为一个项目
  5. 如果项目有子列表,请在子列表上进行合并。
  6. 由于每个项目的行为如此相似,如果我可以使用单个方法而不必使用n方法,每种类型一个,那将是很好的。不幸的是,由于没有任何类型保证是相同的(除了实现上面的一些或所有给定接口之外),创建通用方法证明是困难的。是否有某种方法可以解决这个问题?

    <小时/> 编辑2: 我找到了的方法。基本上,它改为:

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

    不幸的是,此方法需要@SupressWarningsinstanceof,如果可能,我希望避免使用{{1}}和{{1}}。然而,我还没有找到任何其他东西。

1 个答案:

答案 0 :(得分:1)

考虑到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));
}