I am struggling with removing items from my arraylist. More specifically, I have two arraylists, being persons and vulcanos. Both are located in a grid. Each time step, people can move or not (this happens randomly, to the adjecant cells), while volcanos are static during the whole simulation. Volcanos can erupt or not. This is determined by a probability defined by the user. When at a certain timestep a person is located at the same cell as an erupting volcano, this person dies. But I don't know how I can remove that specific person from my array. So far I got the following (is repeated for each time step).
for (int j = 0; j < persons.size(); j++) {
for (int k = 0; k < volcanos.size(); k++) {
if ((persons.get(j).getXCoordPerson()) == (volcanos.get(k).getXCoordVolcano())
&& (persons.get(j).getYCoordPerson()) == (volcanos.get(k).getYCoordVolcano())
&& (volcanos.get(k).getEruptionStatus() == true)) {
// all persons being on the same cell as an erupting volcano die
}
}
}
You can do this with an Iterator too:
for(Iterator<Person> personIterator = persons.iterator(); i.hasNext(); ) {
Person person = personIterator.next();
for(Volcano volcano : volcanos) {
if(volcano.getEruptionStatus() &&
volcano.getYCoordVolcano() == person.getYCoordPerson() &&
volcano.getXCoordVolcano() == person.getXCoordPerson()) {
personIterator.remove();
}
}
}
In this case, you are using the iterator to do the removing, leaving the ArrayList in the state you want as a side effect of the loops.
One thing to watch out for is that you do not modify the list of people during this loop or you will end up with a ConcurrentModificationException. I'm assuming you have one single thread operating, and that this is for schoolwork or something similar. If you were doing this in the real-world, you would have to account for the fact that both lists (people and volcanos) could be changing at any time.
Try to mark your people as dead or harmed(etc.) or add them to another list. Then delete them after loop like
persons.removeAll(deadPeople);
If you don't mind working with Iterable instead of List, and if you don't mind taking dependency on Guava, then why not use Iterables?
Iterable<Person> filtered = Iterables.filter(persons, new Predicate<Person>() {
#Override
public boolean apply(Person person) {
for (Volcano v : volcanos) {
if (v.getEruptionStatus() &&
v.getXCoordVolcano() == person.getXCoordPerson() &&
v.getYCoordVolcano() == person.getYCoordPerson()) {
return false;
}
}
return true;
}
});
This will filter out all dead Persons, and will leave filtered with only living people
Related
I'm trying to make a LinkedList containing the "best of" of an offspring in an evolutionary algorithm.
Therefore, I have my own custom add() method:
public boolean add(Virus v) {
if((this.size()< ConfigObject.getInstance().surviverPopulation //if the size of the new population is < surviverPopulation
|| v.getFitness() > this.getLast().getFitness()) //or the fitness is higher than that of the last member
&& v.getFitness() > 0.0 //and the fitness is higher than 0
&& !v.isDead() //and the virus is alive
&& !this.contains((Virus)v)) { //and it is not yet in the list
super.add(v); //add it normally
Collections.sort(this, new Comparator<Virus>() { //sort the list
//define parameter to sort by
#Override
public int compare(Virus virus1, Virus virus2) { //with custom comparator
if(virus1.getFitness() == virus2.getFitness()) {
return 0;
} else if (virus1.getFitness() > virus2.getFitness()) {
return -1;
} else {
return 1;
}
}
});
}
while(this.size() > 300) {
this.removeLast();
}
return true;
}
With this method, I get a LinkedList of limited size which is also sorted and only contains the "best" objects. (The rest of the LinkedList-class is unaltered).
However, when I use this class, something strange happens:
for(Virus parent : this.currentPopulation) { //for every virus in the current population
for(GraphNode child : parent.getChildren()){ //get all the children, and for each child
temp = (Virus) child;
if(!temp.isDead() && !newCurrentPopulation.contains(child)) { //try to add the child if it's not dead
newCurrentPopulation.add((Virus) child); //and not already in the list
} //(list only takes a maximum of <surviverPopulation>
} //and only the strongest ones, see declaration)
newCurrentPopulation.add(parent); //also try to add the parent to the list if
} //still alive
int j = 0;
for(Virus parent : this.currentPopulation) { //for every virus and its children in the current population
for(GraphNode child : parent.getChildren()){ //check if it made it into the new population
if(!newCurrentPopulation.contains((Virus) child)) {
toRemove.add((Virus) child); //if not, memorize to delete it later
}
}
if(!(newCurrentPopulation.contains((Virus) parent))); {
toRemove.add(parent); //do the same for the parent virus
}
}
It works quite fine for the children, but not for the parent. The debugging info shows that even though the parent (identifiable by an id) is in the newCurrentPopulation, it will be included into the toRemove list (where it's also identifiable by the same id).
Also, I did not override the equals-method for the Virus-class or any of its superclasses. I'm probably missing something quite obvious here but I can't see it.
It is something extremely obvious indeed: the last if-statement is followed by a semicolon and not the {}.
The contains method internally calls the equals method of Virus class.
The default equals method provided by the Object class uses == operator, which in your case returns false.
You have to override the equals method in Virus class and compare the objects with id.
I'm new to Java and still trying to wrap my head around recursion.The function below returns true at the very first intersection between the two sorted lists list x and list y.
public static boolean checkIntersection(List<Integer> x, List<Integer> y) {
int i = 0;
int j = 0;
while (i < x.size() && j < y.size()) {
if (x.get(i).equals(y.get(j))) {
return true;
} else if (x.get(i) < y.get(j)) {
i++;
} else {
j++;
}
}
return false;
}
Now I've been trying to implement it using recursion instead, and I know that there should be a base case which is an empty list in this case and then try to reduce the list by excluding one element at a time and feed it back to the same recursive function, but I can't work out how to check for intersection as I pass the rest of the list over and over.
public static boolean recursiveChecking(List<Integer> x,List<Integer> y) {
if(x.size() == 0){
return false;
}
else {
return recursiveChecking(x.subList(1, x.size()-1), y);
}
}
Any help would be highly appreciated. Thank you.
General approach to making something recursive is to think of two things:
When can I produce an answer trivially? - An answer to this question lets you code the base case. In your situation, you can produce the answer trivially when at least one of two lists is empty (the result would be false) or the initial elements of both non-empty lists are the same (the result would be true)
How do I reduce the problem when the answer is non-trivial? - An answer to this question lets you decide how to make your recursive call. In your case you could, for example, remove the initial element of one of the lists before making the recursive call*, or pass ListIterator<Integer> in place of List<Integer> for a non-destructive solution.
*Of course in this case you need to take care of either adding your numbers back after the call, or make a copy of two lists before starting the recursive chain.
As the lists are ordered, your recursion should remove the first element of the list with the smaller first value. Then you have to return true, if both lists start with the same number and false if any of the lists is empty. Otherwise you keep removing elements. This would look something like this (This code is untested):
public static boolean recursiveChecking(List<Integer> x,List<Integer> y) {
if(x.size() == 0 || y.size() == 0){
return false;
} else if (x.get(0).equals(y.get(0))) {
return true;
} else {
if (x.get(0) < y.get(0)) {
return recursiveChecking(x.subList(1, x.size()-1), y);
} else {
return recursiveChecking(x, y.subList(1, y.size()-1));
}
}
}
My method applyBonus() from the class BonusEmporium gets bonus objects from the arrayList of City objects and applies them to a Player object.
when i write my function like this i have no problem testing it:
public class BonusEmporium extends Bonus {
public BonusEmporium(int cities) {
this.setBonusType(BonusType.EMPORIUM);
this.cities=cities;
setCity(new ArrayList<City>(cities));
}
public void applyBonus(Player player){
Bonus bonus=getCity().get(0).getBonus().get(0);//gets the first bonus from the first
//city
bonus.applyBonus(player);
Bonus bonus=getCity().get(0).getBonus().get(1);//gets the second bonus from the first
//city
bonus.applyBonus(player);
Bonus bonus=getCity().get(1).getBonus().get(0);//gets the first bonus from the
//second city
bonus.applyBonus(player);
}
}
The problem is when i want to run it only while the arraylists contain elements, how do i check that an element from an array is empty?
public class BonusEmporium extends Bonus {
public BonusEmporium(int cities) {
this.setBonusType(BonusType.EMPORIUM);
this.cities=cities;
setCity(new ArrayList<City>(cities));
}
public void applyBonus(Player player){
int i=0,j=0;
while(j<cities){
while(getCity().get(j).getBonus().get(i)!=null){//In theory this should
//verify that the element bonus i from the city j is not empty
//but i get NullPointerException
Bonus bonus=getCity().get(j).getBonus().get(i);
bonus.applyBonus(player);
i++;
}
j++;
}
}
}
It's difficult to tell what you are asking, but you should be able to avoid the error by handling the message chain better.
public void applyBonus(Player player){
List<City> cities = getCity();
for(int i = 0; cities != null && i < cities.size(); i++){
City c = cities.get(i);
List<Bonus> bonuses = c.getBonus();
for (int j = 0; bonuses != null && j < bonuses.size(); j++) {
Bonus b = bonuses.get(j);
if (b != null)
b.applyBonus(player);
}
}
}
You check if the element is empty like this:
if(array != null && array.get(index) == null) // element is null when empty
To check if the array as a whole is empty (has no elements):
if(array != null && array.isEmpty())
In general the problem in java is chaining getters like this:
getCity().get(j).getBonus().get(i)!=null
You can get nullpointer exception from 4 places here. You can check them all like:
if (getCity()!=null &&
getCity().get(j) &&
getCity().get(j).getBonus() &&
getCity().get(j).getBonus().get(i)!=null){
....
}
Other way could be encapsulating whole code in try - catch and catching NPE, which is more like hack.
I also suggest using foreach instead while and don't store array size in separate variables, because you can always get it using
myArr.getSize()
And also check javadoc about ArrayList constructor:
new ArrayList<City>(cities)
because this is likely not doing what you expect
Short story:
init all ArrayLists in constructor (don't specify size)
use foreach loops
don't put nulls into the arrays
and you should be fine without checking for empty elements
My program calls for being able to delete a name and number from a phone book. I have gotten the deleting to work but it only deletes the index from the ArrayList that the text box corresponds to. I need to be able to delete both the name and the number from their respective arraylists by entering it into either texbox. Sorry if there is another answer to this i guess i dont really know how to word it correctly. My code is below.
ArrayList<String> Names = new ArrayList<String>();
ArrayList<String> Numbers = new ArrayList<String>();
if(e.getSource() == DeleteBtn)
{
if (NameTxt.getText() != null)
{
for( int i=0; i<= NamesList.size(); i++)
{
if(NamesList.contains(NameTxt.getText()))
{
NamesList.remove(i);
System.out.println(NamesList.size());
}
}
}
if (PhoneTxt.getText() != null)
{
for( int i=0; i<= NumbersList.size(); i++)
{
if(NumbersList.contains(PhoneTxt.getText()))
{
NumbersList.remove(i);
System.out.println(NumbersList.size());
}
}
}
}
If you HAVE to use ArrayLists then you might consider using an ArrayList of pairs.
You can create your own class, say PhoneBookEntry.
class PhoneBookEntry {
String _name;
String _phone;
// etc...
}
ArrayList<PhoneBookEntry>
Consider using a HashMap instead of the ArrayLists.
HashMap<String, String> numbersAndNames = new HashMap<String, String>();
numbersAndNames.put("John", "123 456 789");
If I were you, I would reconsider my logic. I'm going to try and avoid posting code for you to keep from giving you the answer/doing the work for you but...
I only see you modifying the NamesList variable. You aren't modifying the Names or Numbers ArrayList variables.
I would put your 'contains if statement' some place else. Your checking to see if NameList contains NameText a bunch of times. I don't see why you would need to check it more than once.
If you want to get smart, you can do away with the array completely and just use the getIndex() method to some effect in java...which gets the index corresponding to NameText (I'm being vague here deliberately, so think about what I'm saying).
You can use a HashMap if you want, but it's not necessary.
Per suggestion of using an additional class to track the name/number combo.
ArrayList contacts = new ArrayList();
if(e.getSource() == DeleteBtn) {
if (NameTxt.getText() != null) {
for( int i=0; i<= contacts.size(); i++) {
if(contacts.getName().contains(NameTxt.getText())) {
contacts.remove(i);
System.out.println(contacts.size());
}
}
}
public class PhoneContact {
private String name;
private String number;
/*
Getters and Setters
*/
}
First of all, NumbersList.contains(PhoneTxt.getText()) returns if PhoneTxt.getText() is anywhere in the list.
What you want to check is the NumbersList.get(i).equals(PhoneTxt.getText()) note that i used equals() instead of == operator
my friend actually found the answer, he simply added the other ArrayList(i), thank you to all who posted answers, as they gave me food for thought, just thought the logic of the answer would not work but i was proven wrong, here is the code for anyone interested.
if(e.getSource() == DeleteBtn)
{
if (NameTxt.getText() != null)
{
for( int i=0; i<= NamesList.size(); i++)
{
if(NamesList.contains(NameTxt.getText()))
{
NamesList.remove(i);
NamesList.remove(i);
System.out.println(NamesList.size());
System.out.println(NumbersList.size());
}
}
}
if (PhoneTxt.getText() != null)
{
for( int i=0; i<= NumbersList.size(); i++)
{
if(NumbersList.contains(PhoneTxt.getText()))
{
NumbersList.remove(i);
NamesList.remove(i);
System.out.println(NamesList.size());
System.out.println(NumbersList.size());
}
}
}
}
Well basically I have an assignment that has to be done for January. I have to to create a mock rental service that allow customers to rent cars. I am basing the logic off of an ArrayList, using its methods to manage my car collection.
I have some problems with my code, the logic in a lot of my methods is not working correctly. In the code sample I included the showCar, rentTheCar and returnCar methods are not working as they should. The showCar method displays all the cars, although when invoking the method it asks me for the carNumber. The rentThecar and returnCar seem to be renting/returning all cars, instead of just the one I specify.
I am showing relevant code from my classes below, if anyone can help me figure out where I might have gone wrong.Please I want to make it clear that i do not want my homework done just some guidance. Thanks.
Show car method:
public void showCar (int carNumber)
{
if (cars.size() < 0 ) {
System.out.println ("Add cars first!!!");
}
else if (carNumber < cars.size()) {
System.out.println(cars.get(carNumber));
}
else{
System.out.println("Error!! This note cannot be shown, because it does not exist!!");
}
}
Rent car method:
public void rentTheCar (int carNumber, String CustomerName, String hireDate, String returnDate, int daysOfHire)
{
if (cars.size() < 0) {
System.out.println("Empty list!! Add cars first!!");
}
else if (carNumber > cars.size()) {
System.out.println("This car does not exist!!");
}
else {
for (Car car : cars) {
int index = 0;
cars.get (carNumber);
car.rentTheCar(CustomerName, hireDate, returnDate, daysOfHire);
index ++;
}
}
}
Return car method:
public void returnCar (int carNumber)
{
cars.get(carNumber);
if (cars.size() < 0) {
System.out.println("Error!! It is impossible to return a car from an empty list");
}
else if (carNumber > cars.size()) {
System.out.println("Error!! Not a valis car!!");
}
else {
for (Car car : cars) {
car.returnTheCar();
System.out.println ("The car has been returned correctly");
}
}
}
So what is the purpose of the for loops in ReturnCar and RentTheCar?
What are they doing?
The above clue should put you on the right track.
Your showCar method looks fine, are you sure its showing all the cars in your collection? As far as your other two methods, you are looping over your entire collection and calling your rental operation on each element. You are basing your entire logic off indexed arrays, so use your index.
http://docs.oracle.com/javase/6/docs/api/java/util/List.html
add(int index, E element)
Inserts the specified element at the specified position in this list (optional operation).
get(int index)
Returns the element at the specified position in this list.
I think you should take a look at your foreach loop, maybe you will find a hint or two there! This line:
for (Car car : cars) {
// do something...
}
There is a reason why it is called a for-each loop. :)
Hope I helped.