1

以下のコードでオブジェクト配列の一意のリストを取得するにはどうすればよいですか:

    import java.util.*;

    class t1 {
        public static void main(String[] args) {

            Object[] o1 = new Object[] { null, "abc@aaa.com", "ENG", "775778435", 1};
            Object[] o2 = new Object[] { null, "abc@aaa.com", "ENG", "775778435", 1};

            List<Object[]> result = new ArrayList<Object[]>(); 
            result.add(o1); 
            result.add(o2); 

            // The above result list is coming from some DB & I cannot change the structure of above script. 
            // Now, I need to remove the duplicates from this result list meaning I need to find duplicates from the objects within the list.
            // I tried below code but it still prints duplicates. Any help???

            Set<User> setResult = new HashSet<User>();
            User userInfo = null;

            for (Object[] userData : result) {
                userInfo = new User((String)userData[0], (String)userData[1], (String)userData[2], (String)userData[3], (Integer) userData[4]);
                setResult.add(userInfo);
            }

            Iterator it = setResult.iterator();
            while (it.hasNext()) {
                Object o = it.next();

                User u = (User) o;
                System.out.println("non-duplicate = " + u.getEmail());
            }

            // Expected result: non-duplicate = abc@aaa.com
            // Actual   result: non-duplicate = abc@aaa.com getting printed twice i.e. duplicate not getting removed!
        }
    }

    class User {
        public String firstName;
        public String email;
        public String language;
        public String productCode;
        public int status;

        public User() {         
        }

        public User(String fName, String userId, String lang, String productCode, int status) {
            this.firstName = fName;
            this.email = userId;
            this.language = lang;
            this.productCode = productCode;
            this.status = status;
        }   

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

        public String getLanguage() {
            return language;
        }

        public void setLanguage(String language) {
            this.language = language;
        }

        public String getProductCode() {
            return productCode;
        }

        public void setProductCode(String productCode) {
            this.productCode = productCode;
        }

        public int getStatus() {
            return status;
        }

        public void setStatus(int status) {
            this.status = status;
        }

        @Override
        public int hashCode() {
            int fNameHash = 0;
            int lNameHash = 0;
            int emailHash = 0;
            int langHash = 0;
            int productCodeHash = 0;

            if (this.firstName != null) {
                fNameHash = this.firstName.hashCode();
            }

            if (this.email != null) {
                emailHash = this.email.hashCode();
            }

            if (this.language != null) {
                langHash = this.language.hashCode();
            }

            if (this.productCode != null) {
                productCodeHash = this.productCode.hashCode();
            }

            return (fNameHash + lNameHash + emailHash + langHash + productCodeHash + this.status);
        }

        @Override
        public boolean equals(Object obj) {
            if(obj != null && obj instanceof User) {
                User temp = (User) obj;

                if (this.firstName != null && temp.firstName != null && this.firstName.equalsIgnoreCase(temp.firstName) 
                   && this.email != null && temp.email != null && this.email.equalsIgnoreCase(temp.email) 
                   && this.language != null && temp.language != null && this.language.equalsIgnoreCase(temp.language)
                   && this.productCode != null && temp.productCode != null && this.productCode.equalsIgnoreCase(temp.productCode)
                   && this.status == temp.status) {             
                    return true;
                }
            }
            return false;
        }   
    }

私の予想される結果は、abc@aaa.com を 1 回だけ印刷することですが、2 回印刷されることです!!

このコードを修正する方法を教えてもらえますか?

ありがとう!

4

3 に答える 3

2

問題は、両方のインスタンスにsがあるため、User.equals予測どおりに返されることです。falsenull firstName

if (this.firstName != null && temp.firstName != null && this.firstName.equalsIgnoreCase(temp.firstName) 

その結果、 が同一であっても、が壊れているhashCodeため、一致ではなく単に衝突として扱われます。equals

それを修正してみてください:-)ロジックを次のようなものに置き換えます...

firstName == temp.firstName || firstName != null && firstName.equalsIgnoreCase(temp.firstName)

...動作するはずです;-)

ここで完全に機能するバージョンを確認できます。


余談ですが、 を代入するのを忘れていましlNameHashUser.hashCode

于 2012-08-19T23:34:20.640 に答える
1

equalsメソッドとメソッドの両方hashcodeが正しく実装されていません。

  • 両方のオブジェクトにメンバーがある場合、equalsメソッドは戻ります。falsenull
  • の実装は、hashCode等しいと比較されるいくつかのオブジェクトに対して異なるハッシュ コードを返す場合があります。

でオブジェクトを使用できるようにするにはequals、 との正しい実装を提供する必要があります。hashCodeHashSet

于 2012-08-19T23:35:21.283 に答える
0

問題は、両方のオブジェクトでヌルである firstName 値にあります。このため、 equals() メソッドは false を返し、両方のオブジェクトはSet.

equals と hashcode を次のように変更してみてください。

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof User)) return false;

    User user = (User) o;

    if (status != user.status) return false;
    if (email != null ? !email.equals(user.email) : user.email != null) return false;
    if (firstName != null ? !firstName.equals(user.firstName) : user.firstName != null) return false;
    if (language != null ? !language.equals(user.language) : user.language != null) return false;
    if (productCode != null ? !productCode.equals(user.productCode) : user.productCode != null) return false;

    return true;
}

@Override
public int hashCode() {
    int result = firstName != null ? firstName.hashCode() : 0;
    result = 31 * result + (email != null ? email.hashCode() : 0);
    result = 31 * result + (language != null ? language.hashCode() : 0);
    result = 31 * result + (productCode != null ? productCode.hashCode() : 0);
    result = 31 * result + status;
    return result;
}

最善の方法は、別の回答で提案されているように、IDE から equals と hashcode を生成することです。

于 2012-08-19T23:33:24.250 に答える