Java 中的递归枚举

发布于 2024-09-03 11:09:24 字数 1488 浏览 3 评论 0 原文

我还有一个关于枚举的问题。以下是情况的简要概述。 我有一个 Backpack 类,它有一个 Hashmap 内容,其键为 long 类型的变量,值为带有 Items 的 ArrayList。 我必须编写一个枚举来迭代背包的内容。但这里有一个问题:在一个背包中,还可以有另一个背包。并且枚举还应该能够迭代背包中背包的内容。 (我希望你能理解,我不太擅长解释..)

这是我的代码:

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 temporList.get(i).getEnumeration();”我很担心。用户仍然可以像通常那样使用 hasMoreElemens() 和 nextElement() 吗?

感谢任何帮助,

Harm De Weirdt

I still have a question about Enumerations. Here's a quick sketch of the situation.
I have a class Backpack that has a Hashmap content with as keys a variable of type long, and as value an ArrayList with Items.
I have to write an Enumeration that iterates over the content of a Backpack. But here's the catch: in a Backpack, there can also be another Backpack. And the Enumeration should also be able to iterate over the content of a backpack that is in the backpack. (I hope you can follow, I'm not really good at explaining..)

Here is the code I have:

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

Will this code work decently? It's just the "return temporaryList.get(i).getEnumeration();" I'm worried about. Will the users still be able to use just the hasMoreElemens() and nextElement() like he would normally do?

Any help is appreciated,

Harm De Weirdt

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

那伤。 2024-09-10 11:09:24

您需要创建一个Stack>。当您看到另一个Backpack时,您push该元素上的一个新EnumerationStack中。您始终从堆栈顶部开始nextElement()。如果顶部元素为空,则将其弹出。重复直到Stack.isEmpty()


另一种可能更简单的技术(取决于您对递归的适应程度)是使用“内部”枚举,它本身可以具有内部枚举。以下是在 Object[] 上使用 Iterator 的代码示例。它递归地迭代到任何嵌套的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)

You need to create a Stack<Enumeration<Object>>. When you see another Backpack, you push a new Enumeration on that element into the Stack. You always nextElement() from the top of the stack. If the top element is empty, you pop it off. Repeat until the Stack.isEmpty().


Another perhaps simpler technique (depending on how comfortable you are with recursion) is to use "inner" enumerations, which itself can have inner enumerations. Here's a code sample using Iterator on Object[]. It recursively iterates into any nested 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();
    }       
}

Here's a test harness:

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

This prints:

1 2 3 4 5 6 7 (done)
null (done)
一指流沙 2024-09-10 11:09:24

如果它是出于实用目的而不是家庭作业,我会使用 迭代器接口而不是旧的枚举。对于迭代器,您有一些 apache 集合项目中的不错的实用程序。

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

--编辑--

多基因润滑剂提出了一个很好、优雅的解决方案。我想到了别的事。您可以实现一个通用的 ChainEnumeration 类(实现枚举),它接收枚举列表并允许枚举基础项。在您的树结构中,返回一个简单的枚举,其中一项为叶子,以及一个内部节点的链枚举。

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

If it was for practical purposes and not homework, I would use the Iterator interface instead of the old Enumeration. For iterators you have some nice utilities in the apache collections project.

Secondly, your solution seems to have a bug. The method nextElement() should return the elements themselves, but the line return temporaryList.get(i).getEnumeration() returns an Enumeration object instead.

--EDIT--

polygenelubricants suggested a nice, elegant solution. I thought of something else. You can implement a generic ChainEnumeration class (implements Enumeration), that receives a list of Enumerations and allows enumerating the underlying items. In your tree structure, return a simple enumeration with one item for leafs, and a chain enumeration of inner nodes.

The implementation of ChainEnumeration is simple: it manages a list of iterators, plus a reference to the current active iterator, where items are taken from.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文