LinkedHashSet修改集

时间:2012-12-09 23:28:04

标签: java linkedhashset

我有以下代码:

  private static class Node {
    public LinkedHashSet<String> s = new LinkedHashSet<String>();
    public Node(String s) {
        this.s.add(s);
    }
}

public static void main(String[] args) {
    LinkedHashSet<Node> set1 = new LinkedHashSet<Node>();
    set1.add(new Node("foo"));

    LinkedHashSet<Node> set2 = new LinkedHashSet<Node>(set1);

    LinkedHashSet<String> modifyingSet = new LinkedHashSet<String>();
    modifyingSet.add("modifying foo");

    for(Node n : set2) {
        n.s = new LinkedHashSet<String>(modifyingSet);
        break;
    }

    if (compare(set1, set2)) {
        System.out.println("Equal");
    } else {
        System.out.println("Not Equal");
    }

    return;
 }
private static boolean compare(LinkedHashSet<Node> h1, LinkedHashSet<Node> h2) {
      Iterator<Node> h1i = h1.iterator();
      Iterator<Node> h2i = h2.iterator();
      while (h1i.hasNext()) {
            Node n1 = h1i.next();
            Node n2 = h2i.next();
            if (n1.s.size() != n2.s.size()) {
                return false;
            } else {
                Iterator<String> it1 = n1.s.iterator();
                Iterator<String> it2 = n2.s.iterator();
                while (it1.hasNext()) {
                    String t1 = it1.next();
                    String t2 = it2.next();
                    if(!t1.equals(t2)) {
                        return false;
                    }   
                }           
            }
      }
      return true;
}

当我修改set2时,set1也会被字符串“test”和“bogus”修改。因此,当我比较两个集合时,它们总是相等的(如果每个集合中的字符串相等,则compare()进行比较)

我的问题是:

根据我的理解,Java按值传递,但它似乎是通过引用传递的。任何人都可以帮我解决原因吗?我怎样才能将该集复制到临时集,然后修改集但不修改第一集?

我觉得我在这里错过了一些非常简单的东西。

3 个答案:

答案 0 :(得分:5)

这里有很多问题和误解,所以这是一个清单。

a)您无法修改Set的元素,并希望它仍能正常工作。 Javadoc for Set更具体:

  

注意:如果将可变对象用作set元素,则必须非常小心。如果在对象是集合中的元素的同时以影响等于比较的方式更改对象的值,则不指定集合的​​行为。这种禁止的一个特例是,不允许集合将自己作为一个元素包含在内。

总是假设“未指明的行为”会转换为“它在你的脸上爆炸”,或者说“只有在星期二,当它在Albequerque下雨时才会起作用,所以它可能会工作一半时间并且可能会爆炸另一半。” / p>

b)您必须覆盖hashCode()equals(Object)才能使用HashSetLinkedHashSet中的对象,如果您不希望它们通过{{进行比较1}},看起来你可能不应该在这个应用程序中。

c)Java按值传递引用,这与传递引用的传递值不同。特别是,修改对象将影响对同一对象的所有引用,但更改引用以引用其他对象将不会影响其他引用。

==

d)要复制Set<Foo> set1 = new LinkedHashSet<Foo>(); Set<Foo> set2 = set1; Set<Foo> set3 = set1; set1.add(new Foo()); // set1, set2, and set3 each refer to the same Set, which now contains one Foo set3 = new LinkedHashSet<Foo>(); // set1 and set2 still refer to the Set with one Foo; // set3 now refers to a new empty Set ,只需执行LinkedHashSet

答案 1 :(得分:0)

首先,我建议您使用HashSet。其次,这些结构是不可改变的。您必须调用特定方法来修改集合中的元素。

答案 2 :(得分:0)

我认为compare方法有问题。你可以发布它的实施吗?

for循环不会修改set2。因此,set2应该保持为空,而set1有一些元素。因此,我希望compare方法始终返回false。但是,我怀疑你希望set2保持空白,但这是另一个问题。

<强>更新

compare方法抛出java.util.NoSuchElementException(请参阅http://ideone.com/nv1wmN)。有几个误解会导致这些错误。第一步是在调用set2时意识到compare为空。