首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LinkedHashSet修改集

LinkedHashSet修改集
EN

Stack Overflow用户
提问于 2012-12-09 23:28:04
回答 3查看 1.5K关注 0票数 1

我有以下代码:

代码语言:javascript
复制
  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“和”假冒伪劣“进行修改。因此,当我比较这两个集合时,它们总是相等的(compare()比较每个集合中的字符串是否相等)

我的问题是:

据我理解,Java是通过值传递的,但它似乎是通过引用传递的。有人能帮我找出原因吗?我如何将该集复制到临时集,然后修改该集而不修改第一组?

我觉得我错过了一些很简单的东西。

EN

回答 3

Stack Overflow用户

发布于 2012-12-09 23:34:16

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

( a)您不能修改Set的元素并期望它仍然工作。Set更具体:

注意:如果将可变对象用作set元素,则必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是集合中的元素,则不指定集合的行为。这一禁令的一个特殊情况是,不允许一组将自己作为一个元素加以限制。

总是假设“不明确的行为”意味着“它会在你的脸上爆炸”,或者“它只会在周二在阿尔卑克尔克下雨的时候起作用,所以它可能会工作一半时间,而另一半可能会爆炸。”

( b)如果不希望将hashCode()equals(Object)==进行比较,则必须重写HashSetLinkedHashSet中的对象,在此应用程序中可能不应该这样做。

( c) Java按值传递引用,这与逐值传递和逐引用传递不同.特别是,修改对象将影响到对同一对象的所有引用,但是将引用更改为引用不同的对象将不会对其他引用产生任何影响。

代码语言:javascript
复制
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

( d)要复制LinkedHashSet,只需执行new LinkedHashSet<Foo>(setToCopy)

票数 6
EN

Stack Overflow用户

发布于 2012-12-09 23:31:03

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

票数 0
EN

Stack Overflow用户

发布于 2012-12-09 23:31:51

我认为compare方法是错误的。你能张贴它的实施吗?

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

更新

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13792991

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档