Java中的递归枚举

时间:2010-05-30 08:33:32

标签: java enumeration

我仍然有关于枚举的问题。这是一个情况的快速草图。 我有一个类Backpack,它有一个Hashmap内容,其键为long类型的变量,value为带有Items的ArrayList。 我必须写一个枚举,迭代背包的内容。但这里有一个问题:在背包里,还可以有另一个背包。并且Enumeration还应该能够迭代背包中的背包内容。 (我希望你能效仿,我不是很擅长解释..)

这是我的代码:

public Enumeration<Object> getEnumeration() {
    return new Enumeration<Object>() {
        private int itemsDone = 0;
        //I make a new array with all the values of the HashMap, so I can use
        //them in nextElement()
        Collection<Long> keysCollection = getContent().keySet();            
        Long [] keys = keysCollection.toArray(new Long[keysCollection.size()]);

        public boolean hasMoreElements() {
            if(itemsDone < getContent().size()) {
                return true;
            }else {
                return false;
            }

        }

        public Object nextElement() {               
            ArrayList<Item> temporaryList= getContent().get(keys[itemsDone]);
            for(int i = 0; i < temporaryList.size(); i++) {
                if(temporaryList.get(i) instanceof Backpack) {
                    return temporaryList.get(i).getEnumeration();                       
                }else {
                    return getContent().get(keys[itemsDone++]);
                }
            }
        }
    };

这段代码能否正常运行?它只是“return temporaryList.get(i).getEnumeration();”我对某事感到担心。用户是否仍然可以像通常那样只使用hasMoreElemens()和nextElement()?

感谢任何帮助,

Harm De Weirdt

2 个答案:

答案 0 :(得分:2)

您需要创建Stack<Enumeration<Object>>。当您看到另一个Backpack时,push会将该元素上的EnumerationStack nextElement()。你总是从堆栈的顶部Stack.isEmpty()。如果top元素为空,则将其弹出。重复直到Iterator


另一种可能更简单的技术(取决于递归的舒适程度)是使用“内部”枚举,它本身可以有内部枚举。以下是Object[]上使用Object[]的代码示例。它以递归方式迭代到任何嵌套的public class RecursiveIterator implements Iterator<Object> { final Object[] arr; int index = 0; Iterator<Object> inner; RecursiveIterator(Object[] arr) { this.arr = arr; } @Override public boolean hasNext() { while (true) { if (inner != null) { if (inner.hasNext()) { return true; } else { inner = null; index++; } } if (index == arr.length) return false; if (arr[index] instanceof Object[]) { inner = new RecursiveIterator((Object[]) arr[index]); } else { return true; } } } @Override public Object next() { if (!hasNext()) throw new NoSuchElementException(); return (inner != null) ? inner.next() : arr[index++]; } @Override public void remove() { throw new UnsupportedOperationException(); } }

static void dump(Object[] arr) {
    Iterator<Object> iter = new RecursiveIterator(arr);
    while (iter.hasNext()) {
        System.out.print(iter.next() + " ");
    }
    System.out.println("(done)");
}
public static void main(String[] args) throws FileNotFoundException {
    dump(new Object[] {
        1,
        2,
        new Object[] {
            3,
            new Object[] { 4 },
            5,
        },
        6,
        new Object[] {},
        7,
    });
    dump(new Object[] {
        new Object[] {},
        new Object[] {
            new Object[] {          
                new Object[] {},
            },
        },
        new Object[] {},
        new Object[] { null },
    });
}

这是一个测试工具:

1 2 3 4 5 6 7 (done)
null (done)

打印:

{{1}}

答案 1 :(得分:1)

如果是出于实际目的而不是作业,我会使用Iterator界面而不是旧版Enumeration。对于迭代器,您有一些nice utilities in the apache collections project.

其次,您的解决方案似乎有一个错误。方法nextElement()应返回元素本身,但行返回temporaryList.get(i).getEnumeration()返回一个Enumeration对象。

- 编辑 -

polygenelubricants提出了一个很好的,优雅的解决方案。我想到了别的什么。您可以实现一个通用的ChainEnumeration类(实现Enumeration),它接收枚举列表并允许枚举基础项。在树结构中,返回一个简单的枚举,其中包含一个用于叶子的项目,以及一个内部节点的链枚举。

ChainEnumeration的实现很简单:它管理一个迭代器列表,以及对当前活动迭代器的引用,其中包含项目。