创建一个递归迭代 [英] Creating a recursive iterator

查看:182
本文介绍了创建一个递归迭代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图写一个迭代器类,它们共同构成了一首歌曲的组件层次。所有的类都是抽象的 MusicComponent 基类的实现,并继承的getChildren()功能。摘要 MusicTime 子知道实际的音符/和弦玩,和它的所有实现(例如八分音符,四分音符)返回的getChildren()

I am trying to write an iterator for a hierarchy of classes that collectively make up the components of a song. All classes are implementations of the abstract MusicComponent base class and inherit a getChildren() function. The abstract MusicTime subclass knows the actual note/chord to play, and all its implementations (e.g. quaver, crotchet) return null for getChildren().

其它部件 MusicComponent 持有 MusicTimes 的集合,例如酒吧的时间,而持有的 MusicComponents 歌曲持有部分组成的歌曲如:诗句,合唱团,用不同的节奏节/时的签名。

The other components are MusicComponent which holds a collection of MusicTimes e.g. a bar at a time, and Section which holds the MusicComponents. Song holds the Sections that make up the song e.g. verses, choruses, sections with different tempos/time signatures.

我需要的是一个迭代,将遍历所有部分歌曲,那么所有的 MusicComponents ,只有当它找到一个 MusicTime 传人,戏剧音符的时间是根据它的音符类型的长度,其含有部分的拍号和速度

What I need is an iterator that will iterate through all Sections in a Song, then all MusicComponents in the Section and only when it finds a MusicTime descendant, play the note for the length of time based on its note type, and the time signature and tempo of its containing Section.

抱歉,如果太多的信息,但只有这样,我可以解释我想要做的。所以,我需要处理这一堆,记录其中 MusicComponents 我visted或者是有没有办法这个只是用递归做?

Sorry if too much info, but was the only way I could explain what I'm trying to do. So do I need to handle this with a stack, recording which MusicComponents I've visted or is there a way to do this just using recursion?

推荐答案

您可以写一个迭代器会连接其子的迭代器,甚至懒洋洋地。呼叫下一个()歌曲的迭代器,然后将深入挖掘 MusicComponent 迭代器和最终实现下一个 MusicTime

You can write an iterator which "concatenates" the iterators of its children, even lazily. Calling next() on a Song's iterator would then drill down through the Section and MusicComponent iterators and finally deliver the next MusicTime.

番石榴使这个容易。让 MusicComponent 可迭代< MusicTime> 和实施迭代器()为:

Guava makes this easy. Make MusicComponent an Iterable<MusicTime> and implement iterator() as:

@Override
public Iterator<MusicTime> iterator() {
    return Iterables.concat(getChildren()).iterator();
}

由于所有的孩子都 MusicComponent 和由此实施可迭代&LT; MusicTime&GT; 自己,的迭代器将部分的串联迭代器,这本身就是 MusicTime 迭代器。

Since all children are MusicComponents and thus implement Iterable<MusicTime> themselves, Song's iterator will be a concatenation of Section iterators, which are themselves concatenations of MusicTime iterators.

这最后的迭代器是一种特殊情况。 A MusicTime 迭代器只能返回自己一次:

This last iterator is a special case. A MusicTime iterator should only return itself once:

@Override
public Iterator<MusicTime> iterator() {
    return Iterators.singletonIterator(this);
}

另外,的迭代器可以改为:

Alternatively, Section's iterator could be replaced with:

@Override
public Iterator<MusicTime> iterator() {
    return getChildren().iterator();
}

通过这一点,迭代变得那么容易,因为:

With this, iterating becomes as easy as:

for (MusicTime time : song) {
    player.play(time);
}

您现在可以做任何类型的操作(播放,计算总工期,...)无需重新执行递归。

You can now do any kind of operation (playing, counting the total duration,...) without re-implementing the recursion.

有您的问题的替代解决方案,虽然,但是这一切都归结到设计选择。例如,你可以有一个播放 MusicComponent 其中歌曲通过调用将实施播放所有子女。这是一个简单的递归实现,但你必须为你要添加的 MusicComponent (如所有行动中发挥重复递归 getTotalDuration ,...)。

There are alternative solutions for your problem though, but it all comes down to design choices. For example, you could have a play method on MusicComponent which Song and Section would implement by calling play on all of their children. This is a straightforward recursive implementation, but you must repeat the recursion for all operations you intend to add on MusicComponent (such as play, getTotalDuration, ...).

如果您需要更多的灵活性,您可以使用 Visitor设计模式并让您的播放操作访客(如 PlayVisitor )。这样做的好处是,你可以决定控制从游客中的迭代顺序,但使得它很难增加新的 MusicComponent 的实施。

If you need more flexibility, you could use the Visitor design pattern and make your play operation a visitor (e.g. PlayVisitor). This has the advantage that you can decide to control the iteration order from within the visitor, but makes it harder to add new MusicComponent implementations.

这篇关于创建一个递归迭代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆