Java 集合是否接受重复的 String[]?

Do Java Sets accept duplicate String[]?

在我的 Android 应用程序中,我使用查询来获取 phone 中的所有联系人。我知道这可能会导致重复元素,所以我使用 LinkedHashSet 来处理它:

private void retrieveContacts(ContentResolver contentResolver) {
    LinkedHashSet<String[]> contactSet = new LinkedHashSet<String[]>();
    final Cursor cursor = contentResolver.query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            new String[] {
                    ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                    ContactsContract.CommonDataKinds.Phone.NUMBER }, null,
            null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
    if (cursor == null);
    if (cursor.moveToFirst() == true) {
        do {
            final String name = cursor
                    .getString(cursor
                            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            final String telephone = cursor
                    .getString(cursor
                            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).replace(" ", "").replace("+336", "06");
            String[] contactString = {telephone, name};
            contactSet.add(contactString);
        } while (cursor.moveToNext() == true);
    }

    if (cursor.isClosed() == false) {
        cursor.close();
    }
    for (String[] contactString : contactSet){
        Contact contact = new Contact(contactString[0], contactString[1], false, false);
        daocontact.add(contact);
    }

Contact 是我使用的代表联系人的 Bean,daocontact 是将联系人存储在数据库中的 DAO。问题是,似乎 Set 实际上存储了重复的元素,因为当我根据数据库的记录显示 ListView 时,它显示了很多重复的元素。

为什么 Set 接受重复元素?如何解决这个问题?

String[] 没有 LinkedHashSet 期望保持唯一性的 hashCode()equals 语义。

为了快速修复,请尝试使用 ArrayList<String> 而不是 String[],它确实定义了这些方法。

编辑 - 您可以使用以下习惯用法代替 moveToFirst:

来简化对游标结果的迭代
while (cursor.moveToNext()) {
  // .. use the cursor
}

这是可行的,因为游标语义保证游标将放置在第一个结果(如果有)之前,并且如果没有要移动到的行的下一个值,则return false。

使用 LinkedHashSet<String[]> 不是一个好主意,因为 LinkedHashSet 通过调用 equals 检查重复项,而 String[]equals() 只使用 ==。这意味着 new String[] {"12345", "Joe"}new String[] {"12345", "Joe"} 不被视为相等。

相反,您应该定义一个名为 Contact 的 class,如下所示:

public final class Contact {

    private final String number;
    private final String name;

    public Contact(String number, String name) {
        this.number = number;
        this.name = name;
    }

    public String number() { return number; }

    public String name() { return name; }

    @Override
    public boolean equals(Object object) {
        if (object == this)
            return true;
        if (!(object instanceof Contact))
            return false;
        Contact that = (Contact) object;
        return that.number.equals(number) && that.name.equals(name);
    }

    @Override
    public int hashCode() {
        return number.hashCode() ^ name.hashCode();
    }
}

那你就可以使用LinkedHashSet<Contact>.