Program checks for duplicate input

Viewed 43

I'm pretty much new in java programming and having a hard time doing this. I need to do this program wherein if the user inputs the same pet name, it should tell the user that it is a duplicate. The output should be owner name, pet#1, pet#2, pet#3 and etc.

  public class testingg {
public static void main(String[] args) {
    try (Scanner userInput = new Scanner(System.in)) {
        Pet[] pets = new Pet[100];

        int i;

        System.out.print("Owner's Name: ");
        String owner_Name = userInput.next();
        System.out.print("Owner's Address: ");
        String owner_Address = userInput.next();
        System.out.print("Owner's Contact Number: ");
        int owner_Contactnumber = userInput.nextInt();

        // Asks how many pets are going to avail the vet services
        System.out.print("\nHow many pets are availing Vet services? ");
        int numOfPet = userInput.nextInt();


        for (i = 0; i < numOfPet; i++) {

            // Asks for pet details
            System.out.print("\nPet Name: ");
            String petName = userInput.next();

            pets[i] = new Pet();
            pets[i].petInformations(petName);

            System.out.print("Owner Name: " + owner_Name);
            pets[i].petInfo();
        }
    }
}

}
3 Answers

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.

Store items in an arraylist (arraylist are very beginner friendly), use the .contains(Object o) method on your list. See the docs for the API

you will have to make your Pet class override the

boolean equals(Object arg)

method. A more thorough explanation on this topic has be answered here This way you can determine how a pet differs from others. You need to override it because that is how Arraylist differentiates the objects in it. Partial credit goes to @Hovercraft Full Of Eels for pointing out the deficiency.

You will have to add an import statements to your project. I think it is

import java.util.Arraylist;

logic will look something like

ArrayList<Pet> petList = new ArrayList<>(); 
 


// checking if pet exists

if(!petList.contains(newPet)){
   // .... if pet does not already exist
   petList.add(pet);
}else{
    // ... if it does exist
}
    class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
            System.out.println("please input name");
            String name = sc.nextLine();
            System.out.println("please input pets count");
            int n = sc.nextInt();
            String[] names = new String[n];
            int i = 0;
            while (i < n) {
                // take care of  Carriage return character is treated as character input
                sc = new Scanner(System.in);
                String petNames = sc.nextLine();
                // I also like said upstairs , ArrayList more appropriate than Array
                for (int j = 0; j < n; j++) {
                    if (petNames.equals(names[j])) {
                        System.out.println("this name is repeat");
                        i--;
                        break;
                    }
                }
                names[i] = petNames;
                i++;
            }
            System.out.println(name);
            for (int j = 0; j < n; j++) {
                System.out.print(names[j] + " ");
            }
        }
}

Related