在Java中查找多个HashSet中没有重复元素的所有元素

5
在多个包含整数的HashSet中,我想获取所有没有重复的元素,即那些在所有HashSet的并集中只出现一次的元素。我无法以编程方式概念化它。

例如,考虑第一个集合包含{2,4,6,8,9},第二个集合包含{2,8,9},第三个集合包含{2,4,8,9}。在所有这些集合中,元素6仅出现一次。

如何在Java中找到在多个HashSet中没有重复的所有元素?

你有一组集合,还是它们有明确的数量? - John Dvorak
1
你想要的最终答案是6,对吗? - Fahim Parkar
@FahimParkar:是的,对于上面的例子,答案是6。 - ravi
@JanDvorak:我有多个(确定数量)集合,其中包含整数元素。 - ravi
7个回答

4
你可以保存出现至少一次和至少两次的元素集合。这需要一些手动循环,但是可行。对于任何需要差异的集合都适用,且不会修改输入。
public static Set<E> unique(Set<? extends E>... sets){
   Set<E> once = new HashSet<E>();
   Set<E> twice = new HashSet<E>();

   for(Set<? extends E> set:sets){
      for(E el:set){
         if(once.contains(el)){
            twice.add(el);
         } else {
            once.add(el);
         }
      }
   }

   once.removeAll(twice);
   return once;
} 

Ideone: http://ideone.com/reGDBy 使用示例:
Set<Integer> set1, set2, set3;
...
Set<Integer> u = unique(set1, set2, set3);

评估示例:

例如,考虑第一个集合包含{2,4,6,8,9},第二个集合包含{2,8,9},第三个集合包含{2,4,8,9}。在所有这些集合中,元素6只出现一次。

  • 第一个内部循环完成后,once 包含 {2,4,6,8,9},twice 为空。
  • 添加第二个集合:2、8和9已经在 once 集合中,因此它们被添加到 twice 集合中。
  • once 现在为 {2,4,6,8,9},twice 现在为 {2,8,9}。
  • 从第三个集合开始:2被重新添加到 twice,4被添加到 twice,8和9被重新添加到 twice
  • once 现在为 {2,4,6,8,9}(所有集合的并集),twice 现在为 {2,4,8,9}(至少出现两次的元素)。
  • once 中删除 twiceonce 现在为 {6}。返回 once

你能用三个列表来举例吗?原帖中有三个集合... 用两个集合会更容易... - Fahim Parkar
@JanDvorak:我认为你需要将 public Set<E> unique(Collection<Set<? extends E>> sets) { 更改为 public <E> Set<E> unique(Collection<Set<? extends E>> sets) {。如果您能在这里编译它,那会很有帮助。 - ravi
@JanDvorak:你修改后的帖子中有一个小改动。在第一个内部循环完成后,once包含{2,4,6,8,9},而twice为空。你能否编译并在这里分享你的代码? - ravi
我将在 ideone 中添加一个测试用例。 - John Dvorak
@JanDvorak:当然。我做到了。你很棒。 - ravi
显示剩余4条评论

1
你可以使用contains()方法来实现。首先,从所有其他集合创建一个新的HashSet。然后迭代这个集合并检查其他集合是否contains()指定的元素。如果两个或多个列表都包含它,则您有一个重复项,可以continue。如果只有一个集合包含该元素,则可以将其存储在不同的结果集中。
我编写了一个实用程序方法来实现你所需的功能:
public static <E> HashSet<E> uniques(HashSet<E>... sets){
    HashSet<E> everything = new HashSet<E>();
    for(HashSet<E> set : sets){
        everything.addAll(set);
    }
    HashSet<E> uniques = new HashSet<E>();
    for(E e : everything){
        int count = 0;
        for(HashSet<E> set : sets){
            if(set.contains(e)){
                count++;
            }
            if(count > 1){
                break;
            }
        }
        if(count == 1){
            uniques.add(e);
        }

    }
    return uniques;
}

那么,对于每个集合中的每个元素,如果没有其他集合包含它,就返回该元素? - John Dvorak
@JanDvorak或者存储在结果集中,都无所谓。 - Jakub Zaverka
我恐怕我的方法更快。 - John Dvorak

1

使用中间MultisetGuava版本:

@SafeVarargs
public static <E> Set<E> uniqueElements(Set<? extends E>... sets) {
    final Multiset<E> multiset = HashMultiset.create();
    for (Set<? extends E> set : sets) {
        multiset.addAll(set);
    }
    return Sets.filter(multiset.elementSet(), new Predicate<E>() {
        @Override
        public boolean apply(E element) {
            return multiset.count(element) == 1;
        }
    });
}

这比这个更可取吗?无论如何,我会使用这里描述的代码。 - ravi
1
这段代码需要在您的项目中添加一个额外的库,所以如果您已经在使用Guava,那么您可能更喜欢它。否则,请坚持使用适用于普通JDK的直接方法。 - Natix

0
 public static void main(String[] args) {
        HashSet<Integer> set1 = new HashSet<Integer>();

        set1.add(2);
        set1.add(4);
        set1.add(6);
        set1.add(8);
        set1.add(9);
        HashSet<Integer> set2 = new HashSet<Integer>();
        set2.add(2);
        set2.add(8);
        set2.add(9);
        HashSet<Integer> set3 = new HashSet<Integer>();
        set3.add(2);
        set3.add(4);
        set3.add(8);
        set3.add(9);
        set1.removeAll(set2);
        set1.removeAll(set3);
        System.out.println(set1);
    }

2
那么出现在set2中而不在set1中的元素呢? - John Dvorak
看看这个。我把set1中的6移动到set2,但上面的代码出现了错误... - Fahim Parkar

0
创建两个新的HashSet如何?分别命名为seenOnce和seenMoreThanOnce。
然后,您遍历不同哈希映射中的所有整数。
For each integer:
   If it is in seenMoreThenOnce do nothing.
   else If it is in seenOnce, remove it from seenOnce and add it to seenMoreThenOnce
   Else add it to seenOnce.

当你完成对所有哈希映射的迭代后,seenOnce 将包含仅出现一次的整数。

0
创建一个multiset并迭代它,取出所有计数为1的元素。O(n)

@JanDvorak - 我猜你已经发现顺序错了,已经修复。 - djechlin
@JanDvorak - 它完全没有。感谢您调试我的答案。 - djechlin

-1
public class test {

public static void main(String[] args) throws Exception, IOException {

    int count=0;
    HashSet<Integer> set1 = new HashSet<Integer>();
    HashMap<Integer, String> ee=new HashMap<Integer,String>();
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    System.out.println("how many elements u want to store");
    int n=Integer.parseInt(br.readLine());
    System.out.println("enter te element u want insert");
    for(int i=0;i<n;i++)
    {
        boolean x=set1.add(Integer.parseInt(br.readLine()));
        if(x==false)
        {
            count++;
        }
    }
    System.out.println("no of duplicate elements is   "+count);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接