繁体   English   中英

Java Set 移除“复杂对象”

[英]Java Set removes “complex object”

我总是对 Java Collections (set, map) 删除“复杂对象”感到困惑,我的意思是一些自定义类而不仅仅是原始类型。

我正在尝试:

public class Main {
    public static void main(String[] args) {        
        // set
        Set<Node> set = new HashSet<>();
        set.add(new Node(1,2));
        set.add(new Node(3,4));
        System.out.println(set);
        
        set.remove(new Node(1,2));
        System.out.println(set + "\n");
            
            
        // tree set
        TreeSet<Node> tset = new TreeSet<>((a, b) -> a.name - b.name);
        tset.add(new Node(1,2));
        tset.add(new Node(3,4));
        System.out.println(tset);
        
        tset.remove(new Node(1,2));
        System.out.println(tset);
    }
}

class Node {
    int name;
    int price;
    Node(int name, int price) {
        this.name = name;
        this.price = price;
    }
}

在上面的示例中,打印输出将是:

 Set:
[Node@5ba23b66, Node@2ff4f00f]
[Node@5ba23b66, Node@2ff4f00f]

 TreeSet:
[Node@48140564, Node@58ceff1]
[Node@58ceff1]

显然,一般的 Set 不能删除new Node(1, 2) ,它被视为不同的对象。 但有趣的是 TreeSet 可以删除,我认为这是因为散列代码基于我在这里定义的 lambda 比较器?

如果我更改为 remove new Node(1, 6) ,有趣的是它是相同的打印输出,显然 TreeSet 中的 remove 仅基于名称值。

我想我仍然缺乏对 Set 如何建立散列以及比较器将如何影响它的深入了解。

对于HashMapHashSet ,您需要覆盖hashCode()equals(Object) ,如果两个对象相等,则它们应该具有相同的哈希码。 例如,在您的情况下,您可以这样实现:

@Override
public boolean equals(Object o) {
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    Node node = (Node) o;
    return name == node.name && price == node.price;
}

@Override
public int hashCode() {
    return Objects.hash(name, price);
}

对于TreeMapTreeSet ,相等的概念基于比较(类是否实现Comparable ,或者您提供自定义Comparator )。 在您提供的代码中,您有一个自定义Comparator只考虑name ,因此它会将任何两个具有相同name Node视为相等,而不管它们的price

javadoc 来拯救

https://docs.oracle.com/javase/7/docs/api/java/util/Set.html#remove(java.lang.Object)

如果存在,则从此集合中删除指定的元素(可选操作)。 更正式地,删除元素 e 使得 (o==null ? e==null : o.equals(e)),如果这个集合包含这样一个元素。 如果此集合包含元素(或等效地,如果此集合因调用而更改),则返回 true。 (一旦调用返回,该集合将不包含该元素。)

因此,只需更改您的 Node 类并使用您自己的方法覆盖 equals(Object o) 方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM