2

I'm trying to create a function that should add an item to an ArrayList IF it doesn't exist already in the ArrayList.

This is what I currently have.

Account Class:

public Account() {}

public Account(String accountName, int accountNumber, double accountBalance)
{
    this.AccountName = accountName;
    this.AccountNumber = accountNumber;
    this.AccountBalance = accountBalance;
}

Bank Class:

private ArrayList<Account> accountList;

public Bank() {
}

public boolean addAccount(Account account) {
    if(!accountList.contains(account)) {
        accountList.add(account);
        return true;
    }
    return false;
}

Tester:

public class Main {
    public static void main(String[] args){
        Bank bank = new Bank("qLOwyONvKsM58ZdV& &yo", Bank.BranchLocations.values()[0]);
        Account account = new Account("aucchQitgyzLV", 6329668, 479389.0);
        System.out.println(bank.addAccount(account));
    }
}

It looks like I can add empty accounts without any value but if given optional parameters of 3 values, (name,number,balance) it doesn't accept it. I don't understand

edit;

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Account acc = (Account) obj;
        return AccountBalance == acc.AccountBalance &&
                AccountNumber == acc.AccountNumber &&
                AccountName.equals(acc.AccountName);
    }
  • 9
    What do you mean by "it doesn't accept it" ? Also, calling `contains` doesn't make sense if you don't override `equals(Object)` and `hashcode()` in your `Account` object. – Arnaud Oct 21 '19 at 14:49
  • What you print is the result of `addAccount()` which is boolean. It will be either `true` or `false`. The `toString()` method you added is never called. – Benoit Oct 21 '19 at 14:55
  • If you don't want duplicates, use a data structure that does not allow duplicates instead of one that does (i.e. use a `Set` instead of a `List`). – The Head Rush Oct 21 '19 at 14:57
  • similar read here: https://stackoverflow.com/q/2642589/1004631 – robot_alien Oct 21 '19 at 14:57
  • @Benoit I don't want the toString. i want a true or false if the account is added or not. – Im Yoonah123 Oct 21 '19 at 14:58
  • @Arnaud the account is not being added using the addAccount method, calling the .contain works if the account given is a account() with no optional parameters – Im Yoonah123 Oct 21 '19 at 14:58
  • @ImYoonah123 That's not the problem. It's because the OP probably didn't override `equals` and `hashCode` That should `always` be done, just to be safe. – WJS Oct 21 '19 at 15:00
  • 1
    To be very safe here, I would use a `Set` and just skip the check for `contains(...)`. But before you do that, read the comment given by @WJS. – deHaar Oct 21 '19 at 15:01
  • I have overrided the .equals method. see above @WJS – Im Yoonah123 Oct 21 '19 at 15:01
  • Please show `equals()` and `hashcode()` methods, the problem is likely in there. – Benoit Oct 21 '19 at 15:02
  • @ImYoonah123 Can you please show your class implementation. – WJS Oct 21 '19 at 15:03
  • @ImYoonah123 For a little more information on why you have to override hashcode see here: https://stackoverflow.com/q/2265503/8359764 – hat Oct 21 '19 at 15:07
  • @WJS Done, looks like I edited the toString instead of equals method.. now it should be updated. – Im Yoonah123 Oct 21 '19 at 15:12
  • @deHaar and @ The Head Rush I do not want to use a set instead of arrayList because I don't know how sets work and I feel like ArrayList will be better for my project – Im Yoonah123 Oct 21 '19 at 15:14
  • @Yoonah123 your decision – deHaar Oct 21 '19 at 15:18

3 Answers3

1

From the ArrayList.contains(Object o) javadoc:

Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).

It means, to make your method work correctly, you have to implement the hashcode/equals method in the Account class.

I have created a mock implementation of your code:

No hashcode/equals method defined -> Object class's default hashcode/equals method used which treats each new Object differently.

import java.util.ArrayList;
import java.util.List;

public class Test{


    static class Account {

        private String AccountName;
        private int AccountNumber;
        private double AccountBalance;

        public Account(String accountName, int accountNumber, double accountBalance)
        {
            this.AccountName = accountName;
            this.AccountNumber = accountNumber;
            this.AccountBalance = accountBalance;
        }

        public Account()
        {
        }

        public String getAccountName() {
            return AccountName;
        }

        public void setAccountName(String accountName) {
            AccountName = accountName;
        }

        public int getAccountNumber() {
            return AccountNumber;
        }

        public void setAccountNumber(int accountNumber) {
            AccountNumber = accountNumber;
        }

        public double getAccountBalance() {
            return AccountBalance;
        }

        public void setAccountBalance(double accountBalance) {
            AccountBalance = accountBalance;
        }       


    }

    static class Bank {
    private List<Account> accountList = new ArrayList<>();
    private String inputStr = "";
    private int inputInt = 0;

    public Bank() {
    }

    public Bank(String string, int i) {
        inputStr = string;
        inputInt = i;
    }

    public boolean addAccount(Account account) {
        if(!accountList.contains(account)) {
            accountList.add(account);
            return true;
        }
        return false;
    }

}

        public static void main(String[] args)
        {

            Bank bank = new Bank("qLOwyONvKsM58ZdV& &yo", 1);

            Account account = new Account("aucchQitgyzLV", 6329668, 479389.0);
            Account account5 = new Account("aucchQitgyzLV", 6329668, 479389.0);
            Account account2 = new Account();
            Account account3 = new Account();
            Account account4 = new Account("sgdgrt", 0, 0.1);
            Account account6 = new Account("sgdgrt", 0, 0.1);


            System.out.println( "account added: "+bank.addAccount(account));
            System.out.println("account5 added: "+bank.addAccount(account5));

            System.out.println( "account2 added: "+bank.addAccount(account2));
            System.out.println("account3 added: "+bank.addAccount(account3));

            System.out.println("account4 added: "+bank.addAccount(account4));
            System.out.println("account6 added: "+bank.addAccount(account6));

        }

}

Result:
account added: true
account5 added: true
account2 added: true
account3 added: true
account4 added: true
account6 added: true

Which obviously not correct.

If you would insert the following hashcode/equals methods into the Account class:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    long temp;
    temp = Double.doubleToLongBits(AccountBalance);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    result = prime * result + ((AccountName == null) ? 0 : AccountName.hashCode());
    result = prime * result + AccountNumber;
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Account other = (Account) obj;
    if (Double.doubleToLongBits(AccountBalance) != Double.doubleToLongBits(other.AccountBalance))
        return false;
    if (AccountName == null) {
        if (other.AccountName != null)
            return false;
    } else if (!AccountName.equals(other.AccountName))
        return false;
    if (AccountNumber != other.AccountNumber)
        return false;
    return true;
}  

Result would be:
account added: true
account5 added: false
account2 added: true
account3 added: false
account4 added: true
account6 added: false

So your method would work correctly.

Oliver
  • 1,218
  • 1
  • 17
  • 21
0

After your edits regarding equal, your code must be working as expected.

Instead of using list and checking for duplicates using contains, you could you java.util.Set. It doesnot allow duplicates.
If you want to retain the sequence of insertion then use LinkedHashSet instead. It retains the order of insertions and disallow duplicates. All you have to do is to override equals and hashcode.

import java.util.LinkedHashSet;
import java.util.Set;
public class Bank {
private Set<Account> accountList= new LinkedHashSet<>();

public Bank() {
}

public boolean addAccount(Account account) {
    if(!accountList.contains(account)) {
        accountList.add(account);
        return true;
    }
    return false;
}}
javaGroup456
  • 313
  • 1
  • 6
  • 21
0

I do not know what is going on but I recreated your program and it works as expected. The problem may be with your bank branch logic. I did not override HashCode() but it is a good habit to get into.

    public class BankingDemo {

       public static void main(String[] args) {
          Bank bank = new Bank();
          Account account = new Account("aucchQitgyzLV", 6329668, 479389.0);
          System.out.println(bank.addAccount(account));
          System.out.println(bank.getList());
          System.out.println(bank.addAccount(account));
          System.out.println(bank.getList());
          account = new Account("new account", 29228, 29202.2);
          System.out.println(bank.addAccount(account));
          System.out.println(bank.addAccount(account));
          System.out.println(bank.getList());

       }
    }

    class Account {
       String AccountName;
       int    AccountNumber;
       double AccountBalance;

       public Account() {
       }

       public Account(String accountName, int accountNumber,
             double accountBalance) {
          this.AccountName = accountName;
          this.AccountNumber = accountNumber;
          this.AccountBalance = accountBalance;
       }
       @Override
       public boolean equals(Object obj) {
          if (this == obj) {
             return true;
          }
          if (obj == null || getClass() != obj.getClass()) {
             return false;
          }
          Account acc = (Account) obj;
          return AccountBalance == acc.AccountBalance
                && AccountNumber == acc.AccountNumber
                && AccountName.equals(acc.AccountName);
       }
       @Override
       public String toString() {
          return "{" + AccountName + "," + AccountNumber + "," + AccountBalance
                + "}";
       }
    }

    class Bank {

       private ArrayList<Account> accountList = new ArrayList<>();

       public Bank() {
       }

       public boolean addAccount(Account account) {
          if (!accountList.contains(account)) {
             accountList.add(account);
             return true;
          }
          return false;
       }

       public List<Account> getList() {
          return accountList;
       }
    }
WJS
  • 36,363
  • 4
  • 24
  • 39