Fetching and modifying an object in a set in Java - 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
}

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);

How to change a set to list of different types in java?

Now how to store that values of set in a list. Here the set and list is of different type(ProductAttribute and PersistableProductAttribute).
for(ProductRelationship productrelationship:productRelationshipList)
{
Product product=productrelationship.getRelatedProduct();
PersistableProduct ppTem=new PersistableProduct();
Set<ProductAttribute> aSet = product.getAttributes();
List<PersistableProductAttribute> aList = new ArrayList<PersistableProductAttribute>();
// I need to store here in a list.
}
Its just a simple one I have got it after trying several times by myself.First I need to create a set for PersistableProductAttribute and I have to get the attributes of it using loop and I need to copy that set to list. Now it works fine because the set and list are same type. So we can copy a set to list using add() method in java.
Set<PersistableProductAttribute> ppaSet = new
PersistableProductAttribute<>();
for(ProductAttribute x:aSet)
{
// Get all the attributes here using get()
//and set() methods
// Copy the set to list as follows,
aList.add(ppaSet);
}

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);

ConcurrentModificationExample and possible code simplification

I am throwing a ConcurrentModificationExample in the following code. I checked the API and it has to do with me trying to modify an object while another thread is iterating over it. I am clueless on the matter. I have created a comment above the line causing the exception. The Employee class doesn't contain anything other than the three variables for storing information.
I will be including the entire class as I would also like to know if there is a way to simplify my code as it repeats many things such as object creation and adding everything to the lists.
When you call employeesByAge in here with dep.employees:
dep.employeesByAge(dep.employees)
that will pass in dep.employees to employeesByAge such that in:
public class Department{
LinkedList<Employee> employees = ...;
public LinkedList<Employee> employeesByAge(LinkedList<Employee> outputList) {
...
}
}
both the employee member field and the outputList parameter refers to the same list, not just two list with the same content, but the same list instance.
Then you do:
for (Employee emp: employees){
//the list is null. add the first employee
if (outputList.isEmpty()){
outputList.add(emp);
} else
...
}
which iterates the employee and modifies outputList, but remember that these two are the same list object. Thus, ConcurrentModificationException.
What you're attempting to do is similar to this...
List list = ...;
for(item: list) {
list.add(item);
}
That is, you're updating a collection with elements by iterating over the same collection. All
outputList.add(...);
in Department are adding elements to the collection from the same collection 'employees'.
In main(), by doing
dep.employeesByAge(dep.employees)
you're attempting to update 'dep.employees' with 'dep.employees.' which results in concurrent modification exception.

How to add items found while iterating to an ArrayList?

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.

Categories