我正在寻找迭代的递归方法。
我有一个我想要迭代的对象列表,然后检查它们的子对象。
递归:
doFunction(Object)
while(iterator.hasNext())
{
//doStuff
doFunction(Object.subObjects);
}
我想把它改成像这样的东西
doFunction(Object)
iIterator = hashSet.iterator();
while(Iterator.hasNext()
{
//doStuff
hashSet.addAll(Object.subObjects);
}
对于可怜的伪代码感到抱歉,但基本上我想迭代子对象,同时将新对象附加到列表末尾进行检查。
我可以使用列表执行此操作,并执行类似
的操作while(list.size() > 0)
{
//doStuff
list.addAll(Object.subObjects);
}
但我真的不想添加重复的子对象。 当然我可以在添加它之前检查list.contains(每个subObject)是否。
但我很想用Set来完成那个清洁工。
所以基本上无论如何在迭代它时附加到一个集合,或者是否有更简单的方法使List像集合一样而不是手动检查.contains()?
感谢任何评论。
由于
答案 0 :(得分:5)
我会使用两个数据结构--- 队列(例如ArrayDeque
)来存储要访问其子对象的对象,以及 set (例如HashSet
)用于存储所有访问过的对象而不重复。
Set visited = new HashSet(); // all visited objects
Queue next = new ArrayDeque(); // objects whose subobjects are to be visited
// NOTE: At all times, the objects in "next" are contained in "visited"
// add the first object
visited.add(obj);
Object nextObject = obj;
while (nextObject != null)
{
// do stuff to nextObject
for (Object o : nextObject.subobjects)
{
boolean fresh = visited.add(o);
if (fresh)
{
next.add(o);
}
}
nextObject = next.poll(); // removes the next object to visit, null if empty
}
// Now, "visited" contains all the visited objects
备注:强>
ArrayDeque
是一个节省空间的队列。它被实现为一个循环数组,这意味着你使用的空间比List
更少,当你添加元素时它会不断增长。boolean fresh = visited.add(o)
”结合了“boolean fresh = !visited.contains(o)
”和“if (fresh) visited.add(o)
”。答案 1 :(得分:1)
我认为你的问题本质上是一个需要通过List解决的问题。如果您考虑一下,解决方案的Set版本只是将项目转换为List然后对其进行操作。
当然,与Set.contains()相比,List.contains()是一个缓慢的操作,所以如果速度是一个问题,它可能值得提出混合:
while(list.size() > 0)
{
//doStuff
for each subObject
{
if (!set.contains(subObject))
{
list.add(subObject);
set.add(subObject)
}
}
}
此解决方案快速且概念上也很合理 - 可以将Set视为所有项目的列表,而List是要处理的项目队列。但它确实占用了比单独使用List更多的内存。
答案 2 :(得分:0)
如果不使用List,则在修改集合后,迭代器会在读取它时立即抛出异常。我建议使用List并强制执行插入限制,然后使用ListIterator,这样就可以在迭代时修改列表。
答案 3 :(得分:0)
HashSet nextObjects = new HashSet();
HashSet currentObjects = new HashSet(firstObject.subObjects);
while(currentObjects.size() > 0)
{
Iterator iter = currentObjects.iterator();
while(iter.hasNext())
{
//doStuff
nextObjects.add(subobjects);
}
currentObjects = nextObjects;
nextObjects = new HashSet();
}
我认为这样的事情会做我想要的事情,我并不担心第一个Set包含重复项,只是subObjects可能指向相同的对象。
答案 4 :(得分:0)
使用多个套装并在“回合”中执行:
/* very pseudo-code */
doFunction(Object o) {
Set processed = new HashSet();
Set toProcess = new HashSet();
Set processNext = new HashSet();
toProcess.add(o);
while (toProcess.size() > 0) {
for(it = toProcess.iterator(); it.hasNext();) {
Object o = it.next();
doStuff(o);
processNext.addAll(o.subObjects);
}
processed.addAll(toProcess);
toProcess = processNext;
toProcess.removeAll(processed);
processNext = new HashSet();
}
}
答案 5 :(得分:0)
为什么不创建一个包含整个对象集的附加集?您可以将其用于查找。