I have an aggregate that returns 3 results
{ "serverUsed" : "/127.0.0.1:27017" , "result" : [ { "_id" : "luke" , "times" : 56} , { "_id" : "albert" , "times" : 28} , { "_id" : "matt" , "times" : 28}] , "ok" : 1.0}
however when I try to iterate over the results, the code enter an endless loop (can't understand why!!)
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);
}
Also the output repeats the first result:
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
...
I really don;t understand why this iteration is not working. Please help!
It seems that you are using new iterator every time you access a field in DBObject, ie you're using list.iterator() several times within the loop. list.iterator().next() returns you the first element in the collection. So you end up accessing the first DBObject.
Try this:
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);
}
Or perhaps use a foreach loop:
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);
}
I know, this is an old thread, and it's already been answered, but the answers are optimizations. The actual reason why you are getting the repeated answers is that each time you request .iterator(), it returns back an iterator object that starts from the top of the list.
So the while loop condition of:
list.iterator().hasNext()
will always return true. Correspondingly, the subsequent
list.iterator().next()
will always return back the first element.
What should be done is this:
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);
}
But technically, the for loop mentioned by #Aqua is a lot cleaner to use. This answer was just to clarify the why, not the how.
One possible flaw in your code is you are calling Iterator.next() method multiple times. Store its value in a variable and use variable instead of calling multiple times.
Eg:
DBObject obj = list.iterator().next();
String id = (String) obj.get("_id");
int times = Integer.parseInt(obj.get("times").toString());`
Related
I'm trying to iterate over a list to compare custom objects of . There are a number of different fields in each record but I want to check each record based on two values "EmpNum" and "GroupNum". If the iteration detects a particular EmpNum and GroupNum i want to ignore any other following Record in the list with the same EmpNum and GroupNum afterwards.
I've tried using a for each loop to iterate through which is good for making comparisons but from what I've been reading you shouldn't remove from a list using a for each loop. That any removal should be done using a iterator class. But when I try nested iterator loops to compare couples I'm not sure how to remove the check.
ListIterator<Record> iteration1 = uploadRecordList.listIterator()
if (iteration1.hasNext()){
for (Record record1 = iteration1.next(); iteration1.hasNext();
record1 = iteration1.next()){
ListIterator<Record> iteration2 =
uploadRecordList.listIterator(iteration1.nextIndex());
for (Record record2 = iteration2.next();
iteration2.hasNext(); record2 = iteration2.next()){
System.out.println("---RECORD ONE----")
System.out.println("record1 ID "+ record1.id.toString())
System.out.println("record1 relID = "+ record1.relationshipId.toString())
System.out.println("record1 empID = "+ record1.employeeId.toString())
System.out.println("record1 actionIndicator = "+ record1.actionIndicator.toString())
System.out.println("record1 consultant = "+ record1.consultant)
System.out.println("-----------------")
System.out.println("---RECORD TWO----")
System.out.println("record1 ID "+ record2.id.toString())
System.out.println("record2 relID = "+ record2.relationshipId.toString())
System.out.println("record2 empID = "+ record2.employeeId.toString())
System.out.println("record2 actionIndicator = "+ record2.actionIndicator.toString())
System.out.println("record2 consultant = "+ record2.consultant)
}
}
}
You could create a temporary list and add removed records to it and finally remove temp list from main list.
Else you could use Iterator remove method to avoid ConcurrentModificationException.
Be careful while removing using Iterator remove method, you should remove current object not any object.
I have an application view, where there are list of items. There are say 10 pages with 200 records, 20 records per page. I wish to have the unqiue user count assigned. From the below code I'am able to get the unique records per page. But I wish to get unique user entry throughout the records. So for example while execution if user "Jack" is found, so if the same user is found in later pages I want it to get skipped. Thanks in advance!
Script:
List<WebElement> efirstpagecount = driver.findElements(By.xpath("//*[#id='usersList']/tbody/tr/td[3]"));
Set<String> uniqueUsers = efirstpagecount.stream().map(WebElement::getText).map(String::trim).distinct().collect(Collectors.toSet());
System.out.println("First page count: "+uniqueUsers.size());
You can merge your sets like this:
set1.addAll(set2);
It will add distinct all elements from set2 to a set1.
The code sample:
List<WebElement> efirstpagecount = driver.findElements(By.xpath("//*[#id='usersList']/tbody/tr/td[3]"));
Set<String> uniqueUsers = efirstpagecount.stream().map(WebElement::getText).map(String::trim).distinct().collect(Collectors.toSet());
System.out.println("First page count: "+uniqueUsers.size());
List<WebElement> esecondpagecount = driver.findElements(By.xpath("//*[#id='usersList']/tbody/tr/td[3]"));
Set<String> uniqueUsers2 = esecondpagecount.stream().map(WebElement::getText).map(String::trim).distinct().collect(Collectors.toSet());
uniqueUsers.addAll(uniqueUsers2); // merge two sets
System.out.println("First and second page count: "+uniqueUsers.size());
or this:
Set<String> allUsers = new HashSet();
while(true){
List<WebElement> users = driver.findElements(By.xpath("xpath"));
allUsers.addAll(users.stream().map(WebElement::getText).map(String::trim).distinct().collect(Collectors.toSet()));
// move to next page if exists, else break loop
}
System.out.println("All pages count: " + allUsers.size());
PS performance of addAll() is O(N):
// implementation of addAll() method
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
You can try something like this :
Set<String> set = new HashSet<String>();
List<WebElement> efirstpagecount = driver.findElements(By.xpath("//*[#id='usersList']/tbody/tr/td[3]"));
for(WebElement ele : efirstpagecount){
set.add(ele.getText());
}
This way Set will not have duplicate.
you can get the value as below.
For Example, In the first Page you will get matched list of users.So,add the same in one of set.
HashSet<String> set=new HashSet<>();
List<WebElement> efirstpagecount = driver.findElements(By.xpath("//*[#id='usersList']/tbody/tr/td[3]"))
for(WebElement element :efirstpagecount ){
set.add(element.getText());
}
After doing each pagination then add the below condition as well, then it will keep on adding the value in set Object and finally you can get the
while(hasNextPage)
{
------------------
------------------
List<WebElement> userList = driver.findElements(By.xpath("//*[#id='usersList']/tbody/tr/td[3]"))
for(WebElement element :userList){
set.add(element.getText());
}
------------------
}
Finally, after navigating all the pages, you will have unique set value and you can get the unique count and unique value as below
System.out.println("Unique User No :"+set.size());
for(String user: set){
System.out.println(user);
}
mongodb query is db.test.find({"col1":{"$ne":""}}).count(), I have tried many sources to find the solution, the "col1" must be populated from list array, please help me
I have pasted a part of my code
`
List<String> likey = new ArrayList<String>();
for (DBObject o : out.results())
{
likey.add(o.get("_id").toString());
}
Iterator<String>itkey = likey.iterator();
DBCursor cursor ;
//cursor = table.find();
HashMap<String, String> hashmap = new HashMap<String, String>();
while (itkey.hasNext())
{
System.out.println((String)itkey.next());
String keys = itkey.next().toString();
//System.out.println("keys --> "+keys);
String nullvalue = "";
Boolean listone = table.distinct(keys).contains(nullvalue);
hashmap.put(keys, listone.toString());
//System.out.println("distinct --> "+keys+" "+listone);
//System.out.println("proper str --- >"+ '"'+keys+'"');
}
Iterator<String> keyIterator = hashmap.keySet().iterator();
Iterator<String> valueIterator = hashmap.values().iterator();
while (keyIterator.hasNext()) {
//System.out.println("key: " + keyIterator.next());
while (valueIterator.hasNext()) {
//System.out.println("value: " + valueIterator.next());
//System.out.println("Key: " + keyIterator.next() +""+"value: "+valueIterator.next());
String hashkey = valueIterator.next();
}
}
`
When you post code, it helps if you indent it, so it is more readable. As I mentioned to you on another forum, you need to go back and review the Java collection classes, since you have multiple usage errors in the above code.
Here are a few things you need to do to clean up your code:
1) You don't need to use the itkey iterator. Instead, use:
for (String key : likey)
and get rid of all the itkey.next calls. Your current code only processes every second element of the List. The other ones are printed out.
2) Your HashMap will map a key to a Boolean. Is that what you want? You said you want to count the number of non-zero values for the key. So, the line:
Boolean listone = table.distinct(keys).contains(nullvalue);
is almost certainly in error.
3) When you iterate over the HashMap, you don't need the valueIterator. Instead, get the key (either from the keyIterator, or a variable you define using the simpler iterator syntax above), then use the key to get the matching value using hashmap.get(key).
This will not make your code work, but it will clean it up somewhat - at the moment it is difficult to understand what you are intending it to do.
I am parsing a JSONObject which I extract from a Mongo DB. The number values map to java.lang.number objects according to the documentation, However, I get an error when I try to make the following declarations, specifically in the first System.out.println(value.floatVlaue()).
//For data
int counter = 0;
float score = 0;
Number value = 0;
while(cur.hasNext()){
JSONObject jsonObj = (JSONObject) JSONValue.parse(cur.next().toString());
metricsIterator = ((JSONObject)((JSONObject)((JSONObject)((JSONObject)jsonObj.get("level_1")).get("level_2")).get("level_3")).get("metrics")).keySet().iterator();
while(metricsIterator.hasNext()){
System.out.println(metricsIterator.next().toString());
value = (Number) jsonObj.get(metricsIterator.next());
System.out.println(value.floatValue());
System.out.println(value.toString());
someLogic(value.doubleValue(), ((Number)jsonObj.get("long")).intValue(), start, end, days);
}
}
I think the problem line definitely comes from the value = (Number) jsonObj.get(metrics Iterator.next())
the Json im parsing looks like this
{ "_id" : "9223370663181869423_cnn_1" ,
"long" : 1373672925000 ,
"level_1" :
{ "level_2" :
{ "level_3level" :
{ "metrics" :
{"key1" : 0.003333333333333334 ,
"key2" : 0.005833333333333334 ,
"key3" : 0.005833333333333334 ,
"key4" : 0.009166666666666667 ,
"key5" : 0.1391666666666667 ,
"key6" : 0.1241666666666667 ,
"key7" : 0.01666666666666667
}
}
}
}
}
Thanks so much for any help at all!
Iterators can only be traversed once. This means that once you do metricsIterator.next() in System.out.println(metricsIterator.next().toString());, you end up using up that value and when you call .next() again in value = (Number) jsonObj.get(metricsIterator.next()); you get the value after the one that you are expecting, in other words you skip a value.
As a result when you hit the last value, the next value is null which results in the null pointer.
Try removing the sysout before assignment to value, it should solve the nullpointer.
you are doing twice the metricsIterator.next()
first: System.out.println(metricsIterator.next().toString());
second: value = (Number) jsonObj.get(metricsIterator.next());
then you get to the end without checking if hasNext()
I have created simple table called Reservations and this table have following columns: ID, DUE_DATE, PRODUCTS_PAID, RESERVATION_NAME, SALE, TOTAL_SELL_PRICE and CUSTOMER_ID.
Now what I want to do is that I want to iterate through this table where CUSTOMER_ID is given value. Here is my method that collects all those columns data by CUSTOMER_ID:
public Collection<Reservations> findReservation(int cuID) {
EntityManager em = getEntityManager();
Query q = em.createQuery("SELECT r FROM Reservations r WHERE r.customerData.id = :cID");
q.setParameter("cID", cuID);
List results = q.getResultList();
return results;
}
My problem here is that whenever I run iteration loop it won't stop iterating but it continues to iterate. I have only two rows of data in that table. Can you tell me why this iteration continues and won't stop? Obviously I just want to iterate all data inside of that table based on given CUSTOMER_ID value.
I have tried for loops, for each loops and while loops and non of them works. It must be something to do with my code. Here is one while loop that I tested but it won't stop iteration like the rest loops:
for(Iterator itr2 = rd.findReservation(cuID).iterator(); itr2.hasNext();){
rModel.addRow(Arrays.asList(rd.findReservation(cuID).iterator().next().getId(),
rd.findReservation(cuID).iterator().next().getReservationName(),
rd.findReservation(cuID).iterator().next().getCustomerData().getCustomerName(),
rd.findReservation(cuID).iterator().next().getCustomerData().getCustomerType(),
rd.findReservation(cuID).iterator().next().getDueDate(),
rd.findReservation(cuID).iterator().next().getTotalSellPrice(),
rd.findReservation(cuID).iterator().next().getSale(),
rd.findReservation(cuID).iterator().next().getProductsPaid(),
"Print"));
}
If you wonder what is cuID, its just an integer value which is received from table column. This value is customerID. It works well. So it shouldn't effect on the code. All help is appreciated :)
Because you don't call the next on your iterator that you have declared in the loop. Try this instead :
for(Iterator itr2 = rd.findReservation(cuID).iterator(); itr2.hasNext();){
MyObject obj = itr2.next();
rModel.addRow(Arrays.asList(obj.getId(),
obj.getReservationName(),
obj.getCustomerData().getCustomerName(),
obj.getCustomerData().getCustomerType(),
obj.getDueDate(),
obj.getTotalSellPrice(),
obj.getSale(),
obj.getProductsPaid(),
"Print"));
}
You need to do something like this:-
for(Reservations res : rd.findReservation(cuID)){
// Do whatever you want with this object(res)
rModel.addRow(Arrays.asList(res.getId(), res.getReservationName()...);
}
This is clean and simple! No need to use iterator in that weird way you've used, which just keeps getting a new iterator and keeps fetching the first entry from that, hence leading to an infinite loop!
you use two separate iterators. What you do is this:
while (iterator1.hasNext()) {
iterator2.next();
}
obviously you won't exhaust iterator1. Use the same iterator in your loop and in rModel line:
Iterator it = rd.findReservation(cuID).iterator();
while (it.hasNext()) {
// or whatever your type is
Object next = it.next();
rModel.addRow(Arrays.asList(next.getId(),
next.getReservationName(),
next.getCustomerData().getCustomerName(),
next.getCustomerData().getCustomerType(),
next.getDueDate(),
next.getTotalSellPrice(),
next.getSale(),
next.getProductsPaid(),
"Print"));
}