我有一个返回3个结果的聚合
{ "serverUsed" : "/127.0.0.1:27017" , "result" : [ { "_id" : "luke" , "times" : 56} , { "_id" : "albert" , "times" : 28} , { "_id" : "matt" , "times" : 28}] , "ok" : 1.0}
然而,当我尝试迭代结果时,代码进入无限循环(无法理解为什么!!)
AggregationOutput output = coll.aggregate( match1, unwind, match2, group, sort, limit);
Iterable<DBObject> list= output.results();
while(list.iterator().hasNext()){
String id = (String) list.iterator().next().get("_id");
int times = Integer.parseInt(list.iterator().next().get("times").toString());
System.out.println("ID IS "+id+" time: "+times);
}
输出也重复了第一个结果:
ID IS luke time: 56
ID IS luke time: 56
ID IS luke time: 56
ID IS luke time: 56
ID IS luke time: 56
...
我真的不明白为什么这个迭代不起作用。请帮忙!
答案 0 :(得分:6)
每次访问DBObject
中的字段时,您似乎都在使用新的迭代器,即您在循环中多次使用list.iterator()
。 list.iterator().next()
返回集合中的第一个元素。因此,您最终会访问第一个DBObject
。
试试这个:
Iterable<DBObject> list= output.results();
while(list.iterator().hasNext()){
DBObject obj = list.iterator().next();
String id = obj.get("_id");
int times = Integer.parseInt(obj.get("times").toString());
System.out.println("ID IS "+id+" time: "+times);
}
或者也许使用foreach循环:
for (DBObject obj : output.results()) {
String id = obj.get("_id");
int times = Integer.parseInt(obj.get("times").toString());
System.out.println("ID IS "+id+" time: "+times);
}
答案 1 :(得分:3)
我知道,这是一个旧线程,它已经得到了解答,但答案是优化。实际的原因为什么你得到重复的答案是每次你请求.iterator()时,它返回一个从列表顶部开始的迭代器对象。
所以while循环条件为:
list.iterator().hasNext()
将始终返回true。相应地,随后的
list.iterator().next()
将始终返回第一个元素。
应该做的是:
AggregationOutput output = coll.aggregate( match1, unwind, match2, group, sort, limit);
Iterable<DBObject> list= output.results();
Iterator<DBObject> iterator= list.iterator();
while(iterator.hasNext()){
DBObject obj = iterator.next();
String id = (String) obj.get("_id");
int times = Integer.parseInt(obj.get("times").toString());
System.out.println("ID IS "+id+" time: "+times);
}
但从技术上讲,@ Aqua提到的for循环使用起来要干净得多。这个答案只是为了澄清原因,而不是如何。
答案 2 :(得分:1)
您的代码中的一个可能缺陷是您多次调用Iterator.next()方法。将其值存储在变量中并使用变量而不是多次调用。
例如:
DBObject obj = list.iterator().next();
String id = (String) obj.get("_id");
int times = Integer.parseInt(obj.get("times").toString());`