2D ArrayList Repeating All Entries Java

Viewed 45

I am trying to create a 2D ArrayList but every entry I make is added to a single entry and then repeated. Essentially instead of getting [[a, b, c], [d, e, f]] I'm getting [[a, b, c, d, e, f], [a, b, c, d, e, f]]. Here is my code regarding my issue.

public class Customer {
  
  private String customerId;
  private String name;
  private String address;
  private String phoneNumber;
  
  public Customer(String customerId, String name, Address address, String phoneNumber) {
    this.customerId = customerId;
    this.name = name;
    this.address = address.getAddressInfo();
    this.phoneNumber = phoneNumber;
  }

  public String getCustomerId() {
    return customerId;
  }

  public void setCustomerId(String customerId) {
    this.customerId = customerId;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(Address address) {
    this.address = address.getAddressInfo();
  }

  public String getPhoneNumber() {
    return phoneNumber;
  }

  public void setPhoneNumber(String phoneNumber) {
    this.phoneNumber = phoneNumber;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((address == null) ? 0 : address.hashCode());
    result = prime * result + ((customerId == null) ? 0 : customerId.hashCode());
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    result = prime * result + ((phoneNumber == null) ? 0 : phoneNumber.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Customer other = (Customer) obj;
    if (address == null) {
      if (other.address != null)
        return false;
    } else if (!address.equals(other.address))
      return false;
    if (customerId == null) {
      if (other.customerId != null)
        return false;
    } else if (!customerId.equals(other.customerId))
      return false;
    if (name == null) {
      if (other.name != null)
        return false;
    } else if (!name.equals(other.name))
      return false;
    if (phoneNumber == null) {
      if (other.phoneNumber != null)
        return false;
    } else if (!phoneNumber.equals(other.phoneNumber))
      return false;
    return true;
  }
  
  public String toString() {
    return String.format("ID: %s, Name: %s, Address: %s, Phone: %s", 
        customerId, name, address, phoneNumber);
  }
}
import java.util.ArrayList;
import java.util.List;

public class ParkingOffice {
  
  private String name;
  private String address;
  private List<List<Customer>> customers = new ArrayList<>();
  private List<Customer> customerList = new ArrayList<>();
  
  public ParkingOffice(String name, Address officeAddress) {
    this.name = name;
    this.address = officeAddress.getAddressInfo();
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(Address address) {
    this.address = address.getAddressInfo();
  }

  public List<List<Customer>> getCustomers() {
    return customers;
  }

  public void setCustomers(List<List<Customer>> customers) {
    this.customers = customers;
  }

  public List<Customer> getCustomerList() {
    return customerList;
  }

  public void setCustomerList(List<Customer> customerList) {
    this.customerList = customerList;
  }

  public Customer register(String customerId, String name, Address address, String phone) {
    Customer customer = new Customer(customerId, name, address, phone);
    customer.addCustomers();
    this.customerList.add(customer);
    this.customers.add(this.customerList);
    return customer;
  }

}
import static org.junit.jupiter.api.Assertions.*;

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

import org.junit.jupiter.api.Test;

class ParkingOfficeTest {
  
  Address address = new Address("123 Lane", null, "Anaheim", "CA", "92801");
  Customer customer = new Customer("7g8h9i", "Jane", address, "987654321");
  Customer customer2 = new Customer("4d5e6f", "Joe", address, "987654321");

  @Test
  void testRegisterCustomer() {
    parkingOffice.register(customer.getCustomerId(), customer.getName(), address, customer.getPhoneNumber());
    parkingOffice.register(customer2.getCustomerId(), customer2.getName(), address, customer2.getPhoneNumber());
    List<List<Customer>> customers = parkingOffice.getCustomers();
    assertEquals("[[ID: 7g8h9i, Name: Jane, Address: 123 Lane, Anaheim, CA 92801, Phone: 987654321], [ID: 4d5e6f, Name: Joe, Address: 123 Lane, Anaheim, CA 92801, Phone: 987654321]]", customers);
  }
}
Expected: [[ID: 7g8h9i, Name: Jane, Address: 123 Lane, Anaheim, CA 92801, Phone: 987654321], [ID: 4d5e6f, Name: Joe, Address: 123 Lane, Anaheim, CA 92801, Phone: 987654321]]
Actual: [[ID: 7g8h9i, Name: Jane, Address: 123 Lane, Anaheim, CA 92801, Phone: 987654321, ID: 4d5e6f, Name: Joe, Address: 123 Lane, Anaheim, CA 92801, Phone: 987654321], [ID: 7g8h9i, Name: Jane, Address: 123 Lane, Anaheim, CA 92801, Phone: 987654321, ID: 4d5e6f, Name: Joe, Address: 123 Lane, Anaheim, CA 92801, Phone: 987654321]]

Thank you in advance for any feedback and help.

1 Answers

Your ParkingOffice has a customerList property which is a List of Customer objects. It also has a customers property which is the 2D list you're asking about I think.

When you register a customer you add it to customerList which makes sense. But then you also add that list (customerList) to your 2D list (customers).

So for each new customer you add a new element to each of those two lists: customerList gets the new customer, and customers gets a new element that points to customerList. For customers you are creating an array that looks like [ customerList, customerList, ... ]

It's not clear what customers is supposed to hold but I suspect you could just construct it on request. So in getCustomers() you could return a new list with one element pointing to your customerList.

I also want to point out that you have a subtle bug regarding hash codes. You are calculating the hash code in Customer using mutable properties. Which means that somebody could create an instance of Customer, put it into a hash table (or some other structure that uses hash codes) then modify the name or address of the customer which would change its hash code. When you try to find that customer in the hash table you won't be able to get it back because its hash code has changed.

You should calculate hash codes using only immutable properties.

Related