Java Set 删除 "complex object"

标签 java comparator hashset treeset

我总是对 Java 集合(集合、映射)删除“复杂对象”感到困惑,我指的是一些自定义类而不仅仅是原始类型。

我正在试验:

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 比较器?

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

我认为我对 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,它只考虑 name,因此它会考虑任意两个 Node相同的 name 是平等的,不管它们的 price

关于Java Set 删除 "complex object",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68145518/

相关文章:

java - 将整数映射到对象的最佳方法是什么?以对象作为键

java - Castor 列出多态性

java - 错误 : getText must be called from the UI thread

java - 如何将通用 `Number` 用于 `Comparator.comparing`

java - 需要帮助为我的工作面试代码示例编写比较器

lambda - Java8 Stream 超过一组顺序的一致性

java - 如何设置 JDK NetBeans 在其上运行?

C++ 如何使用用户定义的比较器将 priority_queue 作为属性正确添加到类中?

C# - 使用自定义键定义哈希集

c# - HashSet 枚举器有什么作用?