Sarah
Sarah

Reputation: 1

How to not add duplicates to an arrayList

So brief overview of my assignment: I'm supposed to write an ATM class that uses an accounts class I created. (The accounts class contains methods, open - to create a new account , quit - to exit the current account , login - for a user to login to their account , deposit, withdraw, get balance, and terminate - which breaks out of the infinite loop). My ATM class must keep track of all the opened accounts, so I figure use an array list of type account. For some reason though, the .contains() method is not recognizing duplicates, so it keeps adding accounts that are already there, and I'm not quite sure how to fix this issue. Here's my code: THANKS =)

My account class:

import java.util.ArrayList;

public class Account 
{
    public ArrayList<Account> accounts;
    public static int NextAcctNo = 999;
    private int accountNo;
    private double balance;
public Account() 
{ // constructor

    balance = 0.0; 
    accountNo = ++NextAcctNo;
}

public void Open()
{
    System.out.println("New account number: " + accountNo);
}

public void Quit()
{
    System.out.println("Goodbye");
}

public void Login(int accountNo)
{
    System.out.println("Hello");
    this.accountNo = accountNo;
}

public void Deposit(double amount) 
{ // method
    balance += amount; 
    System.out.println("Deposited: " + amount);
}

public void Withdraw(double amount) 
{ // method
    balance -= amount; 
    System.out.println("Withdrew: " + amount);
}

public double Balance() 
{ // method
    System.out.println("Balance: " + balance);
    return balance; 
}

public void Terminate()
{
    System.out.println("Terminated");
}

public int getAccountNo() 
{ // method
    return accountNo; 
}

}//class Account

my main method:

import java.util.Scanner;
import java.util.ArrayList;

public class ATM 
{

    // search for accounts for D, W, B

    public static void main(String [] args)
    {

        ArrayList<Account> accounts = new ArrayList<Account>();
        int counter = 0;

        while (true)
        {

            Scanner commandScanner = new Scanner(System.in);
            System.out.print("Enter a command - O, Q, L, D, W, B, T: ");
            String command = commandScanner.nextLine();

            if (command.equals("O") == true)
            {   
                Account newAccount = new Account();
                accounts.add(newAccount);
                counter++;
                newAccount.Open();  
            }

            else if (command.equals("Q") == true)
            {
                if (accounts.size() == 0)
                {
                    System.out.println("Error");
                }
                else
                {
                    accounts.get(counter-1).Quit();
                }
            }

            else if (command.equals("L") == true)
            {
                Scanner numberScanner = new Scanner(System.in);
                System.out.println("Enter your account number: ");
                int accountNo = numberScanner.nextInt();
                Account temp = new Account();
                temp.accountNo = accountNo;

                if (counter == 0)
                {
                    accounts.add(temp);
                    counter++;
                }
                else if (counter > 0)
                {
                    if (accounts.contains(temp.accountNo) == true)
                    {
                        counter+=0;
                    }
                    else
                    {
                        Account newAccount = temp;
                        newAccount.Login(accountNo);
                        accounts.add(newAccount);
                        counter++;
                        System.out.println(accounts.size());
                    }
                }




            }

The code is still work in progress, I haven't posted it all - which is why the brackets aren't all closed off.

Upvotes: 0

Views: 882

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347184

ArrayList#contains uses the Object#equals method to determine equality between objects. By default this simple does a comparison of the memory location of the object (o1 == o2)

You will need to override the equals method of the Account class and compare (something like) the account id

public class Account {

    //...

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Account other = (Account) obj;
        if (this.accountNo != other.accountNo) {
            return false;
        }
        return true;
    }

}//class Account

Now, having said this, each time you create a temporary Account you are automatically incrementing the account number, which isn't really desirable.

A better solution would be to use a Map of some kind, keyed to the account number, so that you could simply do something like...

Scanner numberScanner = new Scanner(System.in);
System.out.println("Enter your account number: ");
int accountNo = numberScanner.nextInt();
Account account = accountsMap.get(accountNo);
// Check for a null return result...

This does mean, that each time you create an Account, you will need to add it to the Map, so a factory method of some kind is probably called for...

ps...

There is a contractual link between the equals and the hashCode method, which generally means, when you override one, you should override the other

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes

For example...

public class Account {

    //...

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 43 * hash + this.accountNo;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Account other = (Account) obj;
        if (this.accountNo != other.accountNo) {
            return false;
        }
        return true;
    }

}//class Account

Upvotes: 2

DotNet NF
DotNet NF

Reputation: 833

May have just gone over my head but if you are looking for duplicates of your Account class, why not just add a unique identifier (primary key) whenever one is created ?

Is the data from a database or are you just statically typing entering it? If its from a DB then the primary key is fine. Otherwise just add a Primary Key property to your model and just check to see if any accounts have the same primary key.

Upvotes: 0

Related Questions