将多个 Address 对象从 Person 存储到 TreeSet class

Storing multiple Address objects into a TreeSet from a Person class

基本上,我要做的是为每个 Person 对象存储多个地址。我决定通过将 Address 对象存储在 Person class 的 TreeSet 中来实现这一点。本质上,我想将我创建的每个地址对象的 toString() 存储到我的 TreeSet 中。我通过 Person class 的 addAddress() 方法传递 Address 对象的属性,该方法将属性传递给 Address class.

的构造函数

我在指定行收到错误...

public class Person {
   private TreeSet<Address> addresses = new TreeSet<Address>();

   public void addAddress(String type, String street, String city, String state, String zip) {
     //ERROR ON THIS LINE BELOW
     Address addressObj = new Address(type, street, city, state, zip);
     addresses.add(addressObj);
   }
}

public class Address {
   private String type;
   private String street;
   private String city;
   private String state;
   private String zip;

   @Override
   public String toString() {
       return street + " " + city + " " + ", " + state + " " + zip + ": " + type;
   }

   public Address(String type, String street, String city, String state, String zip) {
       super();
       this.type = type;
       this.street = street;
       this.city = city;
       this.state = state;
       this.zip = zip;
   }
}


public class MainDriver {

   public static void main(String[] args) {
       Person p1 = new Person();
       p1.addAddress("Home", "321 Den Ave", "Orlando", "FL", "32792");
       p1.addAddress("Work", "4411 Alligator Court", "Orlando", "FL", "32792");
   }
}

这是错误消息:

Exception in thread "main" java.lang.ClassCastException: Address cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1294)
at java.util.TreeMap.put(TreeMap.java:538)
at java.util.TreeSet.add(TreeSet.java:255)
at Person.addAddress(Person.java:64)
at MainDriver.main(MainDriver.java:9)

明确一点:我不想将地址存储在一个字符串中,因为我希望以后能够单独操作每个 属性。我也不希望将 Address Class 属性存储在 Person Class 中,因为我需要对 Address Class 进行多次迭代才能为每个 Person 对象存储多个地址。

好吧,TreeSet 要求对元素进行排序。要么你必须构造集合并给它一个知道如何对你添加的对象进行排序的比较器,要么对象本身需要知道如何相互比较。您可以让 Address 实现 Comparable,但为什么要使用 TreeSet?由于您的构造函数正在对 super() 进行不必要的(因为它是隐式的)调用,我猜您是 Java 的新手?也许您不需要 TreeSet 的排序功能,您可以使用 HashSet(如果您只需要唯一性)。无论如何,如果您希望集合执行您期望的操作,您应该重写 hashcode() 和 equals()。如果您使用的是像 Eclipse 或 IDEA 这样的 IDE,那么可能有一个代码模板可以帮助解决这个问题。

基本上您要做的是在 TreeSet 中存储一个对象。

Treeset 是 Sorted Collection,如果您将对象存储在 TreeSet 中,则 Object 应该实现 Comparable 并且您应该提供一个条件,说明对象应该被排序的基础。

这是代码:-

import java.util.Set;
import java.util.TreeSet;

class Person {
    private Set<Address> addresses = new TreeSet<>();

    public void addAddress(String type, String street, String city, String state, String zip) {
        //ERROR ON THIS LINE BELOW
        Address addressObj = new Address(type, street, city, state, zip);
        addresses.add(addressObj);
    }
}

class Address implements Comparable{
    private String type;
    private String street;
    private String city;
    private String state;
    private String zip;

    @Override
    public String toString() {
        return street + " " + city + " " + ", " + state + " " + zip + ": " + type;
    }

    public Address(String type, String street, String city, String state, String zip) {
        super();
        this.type = type;
        this.street = street;
        this.city = city;
        this.state = state;
        this.zip = zip;
    }

    @Override
    public int compareTo(Object o) {
        Address address = (Address)o;
        return this.type.compareTo(address.type);
    }
}


public class MainDriver {

    public static void main(String[] args) {
        Person p1 = new Person();
        p1.addAddress("Home", "321 Den Ave", "Orlando", "FL", "32792");
        p1.addAddress("Work", "4411 Alligator Court", "Orlando", "FL", "32792");
        System.out.println(p1.toString());
    }
}

问题是,要将某些东西放入 TreeSet 中,它们必须具有可比性。这是因为树集会尝试以树结构排列您的项目。如果不能,将抛出异常,因此您放入树集中的所有内容都必须实现 Comparable.

但是,地址不能进行逻辑比较,不是吗?你真的很难为地址写一个 compareTo 方法。你如何确定一个地址是否比另一个地址 "greater"?

因此,我认为 TreeSet 不是适合此目的的数据结构。我建议您改用 HashSet。哈希集要求您的项目实现 hashCode,这是一种 returns 该对象唯一的数字和 equals 的方法。如果对象的哈希码相等,则两个对象在逻辑上也相等。

您可以利用 Objects.hash 来帮助您实现:

@Override
public int hashCode() {
    return Objects,hash(type, street, city, state, zip);
}

或者,使用您的 IDE 生成的实现之一。这是我的 IntelliJ IDEA 得到的:

@Override
public int hashCode() {
    int result = type.hashCode();
    result = 31 * result + street.hashCode();
    result = 31 * result + city.hashCode();
    result = 31 * result + state.hashCode();
    result = 31 * result + zip.hashCode();
    return result;
}

equals方法也应该实现。你可以这样做:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Address address = (Address) o;

    if (!type.equals(address.type)) return false;
    if (!street.equals(address.street)) return false;
    if (!city.equals(address.city)) return false;
    if (!state.equals(address.state)) return false;
    return zip.equals(address.zip);

}