簡體   English   中英

如何修復允許重復的HashSet?

[英]How to fix HashSet that allows duplicates?

我正在將java.util.Set接口與java.util.HashSet實現一起使用,並將其存儲在Map中。

我將一個對象添加到Set中,然后再次檢索Set對象,並能夠添加與第一個對象相等的另一個對象。

當添加看似相等的對象時, Set.add返回true並且兩個相等的對象存儲在HashSet中。 這怎么可能?我該如何解決Set合同的這種明顯的損壞?

我正在通過IntelliJ IDEA 2018.3.6使用Java 12,並檢查了我在java.lang.Object.hashCode實現中添加到Set中的兩個對象的類,兩個對象均返回相同的哈希碼。 我還檢查了java.lang.Objects.equals實現,當使用該方法檢查其相等性時它返回true 兩個對象都包裝在另一個對象Entity中,但這僅轉發對象的hashCodeequals實現。

class Model {

    ...

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof Offer)) {
            return false;
        }

        Offer offer = (Offer) obj;
        return Objects.equals(id, offer.id)
            && Objects.equals(name, offer.name)
            ;
    }

    @Override
    public int hashCode() {
        int result = 1;
        result = 31 * result + Objects.hashCode(id);
        result = 31 * result + Objects.hashCode(name);
        return result;
    }

    ...

}
class Store {

    ...

    private static class Entry {
        Object value;

        Entry(Object value) {
            this.value = value;
        }

        Object getValue() {
            return value;
        }

        @Override
        public boolean equals(Object obj) {
            return Objects.equals(value, obj);
        }

        @Override
        public int hashCode() {
            return value.hashCode();
        }

        @Override
        public String toString() {
            return "Entry[value = " + value + "]";
        }
    }

    ...

    private Map<Class<?>, Set<Entry>> data;

    ...

    private Set<Entry> get(Class<?> type) {
        return data.getOrDefault(type, new HashSet<>());
    }

    @Override
    public void persist(Object obj) {
        Entry entry = new Entry(obj);
        Set<Entry> objects = get(obj.getClass());
        if (objects == null) {
            objects = new HashSet<>();
        }
        if (!objects.add(entry)) {
            throw new ObjectExistsException
                ("Object already exists: " + obj);
        }
        data.put(obj.getClass(), objects);
    }

    ...

}

當Model類型的obj1obj2相等並且objects已經包含包裹在Entry對象中的obj1 ,我希望當obj2包裹在entry並且object.add objects.add(entry)返回false時,不將obj2添加到objects ,然后ObjectExistsException被拋出。

然而,什么是真正的情況是objects.add(entry)返回trueobj2包裹在entity被添加到objects

    @Override
    public boolean equals(Object obj) {
        return Objects.equals(value, obj);
    }

這不是Entry.equals的正確實現。 這可能會將一個Entry與當前條目所保存的值進行比較。 (就像比較一封信和一個信封)。

使您的equals方法檢查obj是否為Entry ,並獲取其值,然后檢查是否相等。

你是正確的@安迪·特納(Andy Turner),但正是@安德里亞斯(Andreas)向我指出了正確的方向。 我以為我會很懶,不寫一個完整的equals方法實現,但是卻花了我很多時間。 應該是這樣的:

private static class Entry {
    ...
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof Entry)) {
            return false;
        }

        Entry entry = (Entry) obj;
        return Objects.equals(getValue(), entry.getValue());
    }
    ...
}

謝謝你倆。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM