For your code to be able to check for duplicate Pet name entries, each time a new pet name String is entered, your code will need to iteratethrough your collection of Pets, either directly or indirectly, checking to see if a duplicate name already exists. Your current code can be edited to do this, but there are some difficulties that don't need to exist due to your using a fixed size array of Pet. These include:
- Before the array is completely filled, it will likely hold null entries, increasing the risk of the code throwing a NullPointerException if you try to dereference a null reference without first checking.
- Also, if you're using a fixed length for loop, then you must take extra care that if a duplicate name is in fact entered, that the loop index not increment. Otherwise you'll leave the array incomplete of needed entries.
Again, this can be solved using your current code, but it might require that you do if (someArrayItem[i] != null) null checks before using your someArrayItem[i] entry.
Better to
- use a dynamic collection of Pets, a
List<Pet> that is initialized as an ArrayList<Pet> to be precise, rather than a Pet[] array of Pet. Then the items held by the collection should not be null, since you will take care to avoid adding null to it.
- Also, I'd use a while loop, not a for loop, since this would make it easier to cleanly handle a loop counter.
- Also, if you use
List<Pet> then you could possibly use the list's .contains(...) method to see if the collection already contains your item of interest -- here to check if the list of pets already has a Pet of the same name. But, there's a problem here. For contains(...) to work, the Pet class must override Object's public boolean equals(Object o) method in such a way that if two Pets have the same pet name, then they will be considered functionally equal. If it doesn't do this, then the contains(...) method will default to the equals method found in the Object class that checks to see if two references are exactly the same, and this will give you the wrong result.
- Also, if you override the equals method, you must also take care to do an equivlant override of the
public int hashCode() method so as not to break the "contract" that equals has (lots has been written about this, and I invite you to search on this topic and read on this to understand it fully, and why it is important.
So one way to solve this would be to wire your Pet class like so:
public class Pet {
private String name;
public Pet(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Pet [name=" + name + "]";
}
@Override // returns true if both name fields are the same
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pet other = (Pet) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override // if equals returns true, then this will return 0
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
And this code can be run like so:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class TestPet {
public static void main(String[] args) {
// create our list of Pet
List<Pet> pets = new ArrayList<>();
Scanner userInput = new Scanner(System.in);
// to simplify, let's just get 4 inputs
int petCount = 4;
// current number of pets entered
int currentCount = 0;
while (currentCount != petCount) {
System.out.print("Please enter a pet name: ");
String petName = userInput.nextLine();
Pet newPet = new Pet(petName);
if (pets.contains(newPet)) {
System.out.println("That name already exists. Please try again");
} else {
pets.add(newPet);
currentCount++;
}
}
// Our list has been filled. Now print it out
System.out.println("Pets: " + pets);
}
}
Otherwise, if you don't want to override equals and would prefer a simpler Pet class, something like:
public class Pet {
private String name;
public Pet(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Pet [name=" + name + "]";
}
}
then you will need to do a more involved test to see if the same name exists.
This can be done with a for loop:
// .... same code above the while loop
while (currentCount != petCount) {
System.out.print("Please enter a pet name: ");
String petName = userInput.nextLine();
// for each loop here:
boolean duplicateFound = false;
for (Pet pet : pets) {
if (petName.equals(pet.getName()) {
// if we found a duplicate name, set flag to true
duplicateFound = true;
}
}
// check flag
if (duplicateFound) {
System.out.println("That name already exists. Please try again");
} else {
pets.add(new Pet(petName));
currentCount++;
}
}
This also can be solved using a newer Java concept of streams:
// .... same code above the while loop
while (currentCount != petCount) {
System.out.print("Please enter a pet name: ");
String petName = userInput.nextLine();
// stream through ArrayList, checking for duplicates
if (pets.stream().filter(p -> p.getName().equalsIgnoreCase(petName)).findFirst().isPresent()) {
System.out.println("That name already exists. Please try again");
} else {
// if not present, then add new Pet
pets.add(new Pet(petName));
currentCount++;
}
}
So you can see that there are several ways to skin a cat.