2

I have been trying most things now but it doesn't seem to work. I want to remove a specific object from an Arraylist if the user enters a specific name. And if not I want the program to print "Can't find dog". I have a getName and toString method in my other class that is working well with all the other options i have in this program, this is the only thing that is not working.

Case 4 is where the removal is supposed to happen. But I also want you to look at Case 3 to compare that Case 3 prints out "can't find dog" no matter what, and case 4 prints out "Cant find dog" as many times as there are objects.

Here is the main method:

ArrayList<Dog> doglist = new ArrayList<Dog>();
Scanner myscan = new Scanner(System.in);
boolean running = true;

while (running) {
    System.out.println("\n************************************");
    System.out.println("\nVälkommen till Kennelklubben!");
    System.out.println("\n************************************");
    System.out.println("\n[1] Register new dog");
    System.out.println("[2] Print out list");
    System.out.println("[3] Increase age");
    System.out.println("[4] Remove dog");
    System.out.println("[5] Quit program");
    System.out.println("\n************************************");
    System.out.println("\nChoose: ");

    int option = myscan.nextInt();

    switch (option) {
        case 1:
            System.out.println("Write name:");
            String name = myscan.next();
            System.out.println("Write race:");
            String race = myscan.next();
            System.out.println("Age:");
            int age = myscan.nextInt();
            System.out.println("Weight:");
            double weight = myscan.nextDouble();

            Dog dog = new Dog(name, race, age, weight);

            doglist.add(dog);

            break;
        case 2:
            System.out.println("Minimum length of tail:");
            double userInput1 = myscan.nextDouble();

            for (Dog d : doglist) {
                if (d.getTailLength() >= userInput1) {
                    System.out.println(d.toString());
                } else {
                    System.out.println("Can't find dog");
                }
            }
            break;
        case 3:
            System.out.println("Name of dog:");
            String userInput2 = myscan.next();

            for (Dog d : doglist) {
                if (d.getName().equals(userInput2)) {
                    d.increaseAge();
                    break;
                }
            }
            System.out.println("Can't find dog");
            break;
        case 4:
            System.out.println("Name of dog:");
            String userInput3 = myscan.next();
            for (Dog d : doglist) {
                if (d.getName().equals(userInput3)) {
                    doglist.remove(d.toString());
                } else {
                    System.out.println("Can't find dog");
                }
            }
            break;
        case 5:
            running = false;//Avslutar loopen och därmed programmet
            System.out.println("Programmet avslutat");
            break;
        default:
            System.out.println("Nu blev det fel, välj mellan [1] [2] [3] [4] [5]");//Felmeddelande om valet är någon annan siffra än de som menyn innehåller
            break;
    }
}

Here is the other class with my methods

public class Dog
{
    private String name;
    private String race;
    private int age;
    private double weight;
    private double tailLength;

    public Dog (String name, String race, int age, double weight)
    {
        this.name = name;
        this.setRace(race);
        this.age = age;
        this.weight = weight;

        if(race.equals("tax"))
        {
            this.setTailLength(3.7);
        }
        else
        {
            this.setTailLength((age - weight) / 10);
        }
    }


    public String getRace()
    {
        return race;
    }

    public void setRace(String race)
    {
        this.race = race;
    }

    public double getTailLength()
    {
        return tailLength;
    }

    public void setTailLength(double tailLength)
    {
        this.tailLength = tailLength;
    }

    public int increaseAge()
    {
        age++;
        return age;
    }

    public String toString()
    {
        return name + " " + getRace() +
                " " + age + " " + "år" + " " + weight + " " + "kg" + " " + getTailLength();
    }

    public String getName()
    {
        return name;
    }
}
Michael
  • 41,989
  • 11
  • 82
  • 128
  • 2
    You are on your way to encounter a nasty exception called [`ConcurrentModificationException`](https://docs.oracle.com/javase/8/docs/api/java/util/ConcurrentModificationException.html). This happens when you are iterating over a list and try to remove an item from the list at the same time – smac89 Dec 11 '17 at 16:25
  • you can't remove by name in case 4 – information_interchange Dec 11 '17 at 16:25
  • Is it possible to have multiple dogs with the same name in that list? – smac89 Dec 11 '17 at 16:29
  • @smac89 Ok i see, but how would i do this if i want to remove the object by name? – mackanmorre Dec 11 '17 at 16:29
  • @smac89 it is possible, but we can assume that it is not for now, if that makes things easier? – mackanmorre Dec 11 '17 at 16:30

3 Answers3

2

For clarity's sake, here's what you currently have:

            System.out.println("Name of dog:");
            String userInput3 = myscan.next();

            for(Dog d : doglist) 
            {
                if(d.getName().equals(userInput3)) 
                {
                    doglist.remove(d.toString());
                }
                else
                {
                    System.out.println("Can't find dog");
                }
            }

            break;

dogList is a ArrayList<Dog>.

ArrayList.remove()'s documentation states:

Removes the first occurrence of the specified element from this list, if it is present. If the list does not contain the element, it is unchanged.

Here, you're calling remove() with the parameter d.toString(). d is the instance of Dog that you want to remove. d.toString() returns a String.

So dogList.remove(d.toString()) will attempt to remove the String from the list. Obviously this String is not in the list as it is a list of Dog. This String will not be found and nothing will be removed.

As the documentation says, you need to pass the instance that you want to remove. You would need to call doglist.remove(d). This however will cause an error since you can't remove items from a list while you are iterating on it.

Thus, you need to store the Dog instance in a temporary variable and remove it after you have iterated on it.

Something like this would work:

Dog dogToRemove = null;
for (Dog d: dogList) {
    if (d.getName().equals(userInput3)) {
        dogToRemove = d;
    }
}

if (dogToRemove == null) {
    System.out.println("Could not find dog with name " + userInput3);
} else {
    dogList.remove(dogToRemove);
}

Note that there are other ways to do this, this is just one of them. I encourage you to find alternatives so you understand how this works better.

GuiSim
  • 7,361
  • 6
  • 40
  • 50
1

For case 3 :

  • Try to add an else and put in your message there

            System.out.println("Name of dog:");
            String userInput2 = myscan.next();
    
            for (Dog d : doglist) {
                if (d.getName().equals(userInput2)) {
                    d.increaseAge();
                    break;
                }
                else {
                    System.out.println("Can't find dog");
                }
            }
    
            break;
    

For case 4 : You can remove by Index

System.out.println("Name of dog:");
            String userInput3 = myscan.next();
            for (Dog d : doglist) {
                if (d.getName().equals(userInput3)) {
                    doglist.remove(doglist.indexOf(d));
                } else {
                    System.out.println("Can't find dog");
                }
            }
            break;
NeptuneZ
  • 608
  • 1
  • 10
  • 23
  • 1
    Unfortunately it still prints out "can't find dog" even when it finds the dog and increases the age? – mackanmorre Dec 11 '17 at 16:48
  • It prints out "can't find dog" one time ? – NeptuneZ Dec 11 '17 at 16:50
  • yes exactly :) Prints it out one time no matter what – mackanmorre Dec 11 '17 at 16:51
  • Are you sure that you did remove the Sysout outside the loop ? – NeptuneZ Dec 11 '17 at 16:58
  • It works now, it wasn't the sysout but just a small error on my part, thx for the help :) – mackanmorre Dec 11 '17 at 17:03
  • can you explain more to help you ? – NeptuneZ Dec 11 '17 at 17:09
  • for(Dog d : doglist) { if(d.getName().equals(userInput2)) { d.increaseAge(); break; } else { System.out.println("Can't find dog with name:" + userInput2); } } break; – mackanmorre Dec 11 '17 at 17:10
  • What happens is that when it can't find the name, it prints out "can't find dog" 3 times if there are 3 objects. And when it finds the dog, it still prints it out 1 time? – mackanmorre Dec 11 '17 at 17:11
  • 1
    Try this code : `case 3: System.out.println("Name of dog:"); String userInput2 = myscan.next(); int flag = 0; for(Dog d : doglist) { if(d.getName().equals(userInput2)) { d.increaseAge(); flag = 1; break; } } if (flag == 0){ System.out.println("Can't find dog with name:" + userInput2); } break;` – NeptuneZ Dec 11 '17 at 17:17
  • You're welcome , if it works you can vote up to make it visible for other users . – NeptuneZ Dec 11 '17 at 17:27
1

There is a better way to do this with Java 8.

doglist = doglist.stream().filter(dog -> !dog.getName().equals(userInput3)).collect(toList());

One line of code, easily readable, and no moving parts

And if you want a message if the dog is not found then:

if (doglist.stream().anyMatch(dog -> dog.getName().equals(userInput3)){
  doglist = doglist.stream().filter(dog -> !dog.getName().equals(userInput3)).collect(toList());
} else {
   System.out.println("Can't find dog");
}
robjwilkins
  • 5,462
  • 5
  • 43
  • 59