How to add items found while iterating to an ArrayList? - java

ArrayList<Persons> persList = new ArrayList<Persons>();
for(Persons p : persList){
Persons pers = new Persons();
pers = service.getPersons(id);
p.setAddress(pers.getAddress());
persList.add(pers);
}
Is this the right way to add all found Persons to persList? Thank you in advance.

No, you shouldn't modify a list while you're iterating over it, other than via the Iterator.remove method. Aside from anything else, even if this code didn't throw an exception, it would go on forever unless persList was empty... there's always be new people to iterate over!
You should basically create a new list collecting the items to add, and then use addAll at the end:
ArrayList<Persons> persList = new ArrayList<Persons>();
// Populate the list, presumably
List<Persons> extraPeople = new ArrayList<Persons>();
for(Persons p : persList){
// Note: there's no point in creating a new object only to ignore it...
Persons pers = service.getPersons(id);
p.setAddress(pers.getAddress());
extraPeople.add(pers);
}
persList.addAll(extraPeople);
This code still doesn't make much sense in my view, as you're fetching via the same id value on every iteration... I can only hope this was an example rather than real code.
Also note that if each instance of your Persons class is meant to be a single person, it would be better to call it Person.

Related

Java console - Remove element from arraylist, still shows up when printing

I have an arraylist which I can add to using constructors. That works perfectly fine, and they show up when printing, but when I remove them, it still shows up in the list when printing, even though when I try to remove it for a second time, it says "NullPointerException", or goes to my failsafe else if. The problem therefore have to be in the printing part, or am I thinking completely incorrectly? Is it not updating the arraylist after removing an element?
Thank you.
Instance stuff - Creating Arraylist/constructor(employeeVar = int)
static Employees[] employee = new Employees[employeeVar];
static List<Employees> EmployeesAL = new ArrayList<>(Arrays.asList(employee));
Printing Arraylist
else{
System.out.println("id: " + EmployeesAL.get(i).getEmployeeID() + "Name: " + EmployeesAL.get(i).getEmployeeName());
}
Removing element
else if (employee[idToRemove].getEmployeeID() == idToRemove && customer[idToRemove].getEmployeeName() != null){
EmployeesAL.remove(idToRemove);
employee[idToRemove] = null;
}
}
The way you set it up, EmployeesAL and employee are completely unbound. A change in one is not reflected in the other.
So, when you have: [Jane, Joe, Jack] in your employee, that means at first, EmployeesAL is also [Jane, Joe, Jack]. But if you then remove an employee, the effect is that the entry in the array is nulled out, but the entry in the arraylist is removed. So, removing Joe results in employee being [Jane, null, Jack] and EmployeesAL being [Jane, Jack]. Now Jack's position in the array is index 2 (employee[2]) and in the arraylist it's 1: EmployeesAL.get(1). Your code checks employee[idToRemove] and then asks EmployeeAL to remove that index, which, obviously, is going to fail.
Why do you have 2 data structures with the same data? Stop doing that. Pick one: Either have Employee[] employees, or have List<Employee>. You probably want only the latter:
List<Employee> employees = new ArrayList<>();
employees.addAll(Arrays.asList(new Employee("Jane"), new Employee("Joe"), etc);

Fetching and modifying an object in a set in Java

I have MyFinalSalad class consisting of the following elements:
AppleClass apple;
BananaClass banana;
PearClass pear;
List<SpicesClass> spices;
I have equals implemented such as 2 MyFinalSalad objects are equal, if they have same AppleClass, BananaClass, PearClass objects in them.
Now, I am creating a set of MyFinalSalad objects.
And I have the following code:
MyFinalSalad mySalad = new MyFinalSalad(apple, banana, pear);
SpiceClass cinnamon = new SpiceClass("cinnamon");
if (mySet.contains(mySalad)) {
// I want to fetch mySalad object in the set and add cinnamon to the list of spices
} else {
List<SpiceClass> spices = new ArrayList<>();
spices.add(cinnamon);
mySalad.setSpices(spices);
mySet.add(mySalad);
}
To summarize, if mySalad is already present in mySet, add the spice object to the list of spices in mySalad from mySet, else add mySalad to mySet after creating a new spice list, adding cinnamon to it and inserting list in mySalad.
My question is, if set already has mySalad and I want to add a new spice to the list in that object, how do I achieve it?
From https://stackoverflow.com/a/7283419/887235 I have the following:
mySet.stream().filter(mySalad::equals).findAny().orElse(null).getSpices().add(cinnamon);
Is this the only way or the right way to do it? Or is there a better way?
I was thinking that as I am already entering if after doing a contains check, orElse(null) will never be encountered. Thus null.getSpices() will never occur. Is this assumption correct?
Is there a better way to do it?
I cannot change Set to Map.
Your assumption is correct. The orElse(null) will never take place since you check if the set contains the salad right before. You could replace it with get().
However, I would also go one level before and handle it as an Optional, taking the advantage of isPresent and get method.
Salad mySalad = new Salad();
Optional<Salad> possibleSalad = set.stream().filter(mySalad::equals).findAny();
if (possibleSalad.isPresent()) {
Salad alreadyExistingSalad = possibleSalad.get();
// combine spices
} else {
// add new salad
}

How to remove new ArrayList<>?

I have try methods like remove, removeAll, delete. But all of these words is not available in android studio. What word should i used instead?
public List<ContactObject> receipt = new ArrayList<>();
receipt.add(new ContactObject(object.product_title, object.product_price,
object.img1, object.quantity));
I know how to add to the list receipt, but how to remove the data added?
The remove() of an ArrayList depends on the implementation of equals() method, in your case in ContactObject.
Invoking remove() then will solve your issue.
receipts.remove(contactObject);
If you don't add the new object directly, you can remove it like this:
List<ContactObject> receipts = new ArrayList<>();
ContactObject contactObject = new ContactObject(object.product_title, object.product_price,
object.img1, object.quantity)
receipts.add(contactObject);
// Remove previous added object
receipts.remove(contactObject);
removeAll removes all the given objects and returns the state of the operation.while remove only remove the object that is currently provided.
In your case you want to remove a single object by
yourarraylist.remove(yourobject);

Array of hashmap with one hashmap

Im working on a school assignment, and im supposed to make a array of hashmap like this:
HashMap<String, Person>[] mood = (HashMap<String, Person>[]) new HashMap<?, ?>[6];
im reading from a file, it goes something like this. the problem is that it gives NullPointerException where i try to put the mood into mood[0]! cant find anything about how the hashmap-array works in my books.. :( would be happy for all help (:
Person p = new Person();
p.name = word[1];
p.age = word[2];
p.mood = word[3];
people.put(p.name, p);
if (p.mood.equals("HAPPY")) {
mood[0].put(p.mood, p); //NullPointerException
}
Basically, you did initialize an array of mood, but it's initialized with nulls. So before you can call any method on mood[0] (or at any other indices), you need to put a non-null object inside mood[0].
When you create arrays of objects, the array elements are initially null, so before using mood[0], you need to populate it with an instance of HashMap<String, Person>

What causes this retainAll exception?

java.lang.UnsupportedOperationException: This operation is not supported on Query Results
at org.datanucleus.store.query.AbstractQueryResult.contains(AbstractQueryResult.java:250)
at java.util.AbstractCollection.retainAll(AbstractCollection.java:369)
at namespace.MyServlet.doGet(MyServlet.java:101)
I'm attempting to take one list I retrieved from a datastore query, and keep only the results which are also in a list I retrieved from a list of keys. Both my lists are populated as expected, but I can't seem to user retainAll on either one of them.
// List<Data> listOne = new ArrayList(query.execute(theQuery));
// DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
// List<Data> listTwo = new ArrayList(ds.get(keys).values());
// listOne.retainAll(listTwo);
EDIT
Ok, in an attempt to simplify, since this is apparently multiple problems in one, I have stopped using the low level API for datastore and instead of am just pulling one by one with a loop.
List<MyClass> test = (List<MyClass>) query.execute();
List<MyClass> test2 = new ArrayList<MyClass>();
for (String key : favorites) {
test2.add(pm.getObjectById(MyClass.class, key));
}
log.info(test.toString());
test.retainAll(test2);
The above works. It doesn't throw the exception. The below does throw the exception. The only difference is the log.info. I'm stumped.
List<MyClass> test = (List<MyClass>) query.execute();
List<MyClass> test2 = new ArrayList<MyClass>();
for (String key : favorites) {
test2.add(pm.getObjectById(MyClass.class, key));
}
test.retainAll(test2);
It will not let me do new ArrayList() on the query result since it returns an array of objects.
You however need to put them in a new ArrayList(). The returned List implementation apparently doesn't support retainAll(). That's what the exception is telling you.
A "plain" ArrayList supports it. If passing through the ArrayList constructor is not possible due to difference in generic type, then you'll need to manually loop over it and cast each item before adding.
List<Data> listTwo = new ArrayList<Data>();
for (Object object : ds.get(keys).values()) {
listTwo.add((Data) object);
}
listOne.retainAll(listTwo);
Update: as per your update, the entities are apparently lazily loaded/filled. Most ORM's (DataNucleus is one) may indeed do that. As I don't use DataNucleus, I can't go in detail how to fix that in a "nice" way. But you at least now know the root cause of the problem and it can be solved the same way as above. Fill the list test in a loop as well.
If the type of collection you use for your "list of keys" does not support retainAll that exception will be thrown. Which type are you using?
TIP: you don't need to iterate to fill listTwo.
just do:
listTwo.addAll(ds.get(keys).values())

Categories