5

In multiple HashSet of Integers I want to get all those elements, which has no duplicate. i.e. which came only once in union of all the HashSet. I am not able to conceptualize it programmatically.

As an example, consider set first contains {2,4,6,8,9}, second set contains {2,8,9} and third set contains {2,4,8,9}. In all these set, element 6 occurs only once.

How to find all the elements which has no duplicate in multiple HashSet of Integers in Java?

ravi
  • 6,140
  • 18
  • 77
  • 154

7 Answers7

4

You could hold the set of elements that occur at least once and at least twice. It's a bit of manual looping but it's possible. This will work for any number of sets to difference and will not modify the input:

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

Example usage:

Set<Integer> set1, set2, set3;
...
Set<Integer> u = unique(set1, set2, set3);

Example of evaluation:

As an example, consider set first contains {2,4,6,8,9}, second set contains {2,8,9} and third set contains {2,4,8,9}. In all these set, element 6 occurs only once.

  • After the first inner loop completes, once contains {2,4,6,8,9} and twice is empty.
  • Adding the second set: 2, 8 and 9 are already in the once set, so they are added to the twice set.
  • once is now {2,4,6,8,9}, twice is now {2,8,9}.
  • From the third set: 2 is re-added to twice, 4 is added to twice, 8, 9 are re-added to twice.
  • once is now {2,4,6,8,9} (union of all sets), twice is now {2,4,8,9} (elements that occur at least twice).
  • remove twice from once. once is now {6}. Return once.
John Dvorak
  • 26,799
  • 13
  • 69
  • 83
  • can you have this example with three lists? OP has 3 sets... with 2 sets its easier... – Fahim Parkar Dec 08 '12 at 15:36
  • @FahimParkar modified to use varargs and added an example. – John Dvorak Dec 08 '12 at 15:47
  • @JanDvorak: I think you need to change `public Set unique(Collection> sets) {` to `public Set unique(Collection> sets) {` . Also would be helpful if you can compile it [here](http://ideone.com) – ravi Dec 08 '12 at 15:53
  • @JanDvorak: There is a minor change in you modified post.`After the first inner loop completes, once contains {2,4,6,8,9} and twice is empty.`. Can you compile and share your code [here](http://ideone.com) – ravi Dec 08 '12 at 16:01
  • I will add a test case to ideone. – John Dvorak Dec 08 '12 at 16:03
  • @JanDvorak: [Here](http://ideone.com/osTba6) `Main` method is empty. U cn call ur method to make it more clear. Anyways thank you. – ravi Dec 08 '12 at 16:09
  • @RaviJoshi updated with an example. Added `static` as well - no need for it to be an instance method. – John Dvorak Dec 08 '12 at 16:19
  • @JanDvorak: Cool enough... I too had added `static` in my eclipse code as well. Thank you buddy. – ravi Dec 08 '12 at 16:29
  • @JanDvorak: Sure. I did it. you rock. – ravi Dec 08 '12 at 16:33
1

You could do that using the contains() method. First, create a new HashSet from all the other sets. Then iterate over this set and check if other sets contains() the specified element. If two or more lists contain it, then you have a duplicate and can continue. If only one set contains the element, you can store it somewhere in a different result set for example.

I wrote a utility method to achieve what you need:

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;
}
Jakub Zaverka
  • 8,816
  • 3
  • 32
  • 48
1

A Guava version using intermediate Multiset:

@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;
        }
    });
}
Natix
  • 14,017
  • 7
  • 54
  • 69
  • Is it preferable than [this](http://stackoverflow.com/a/13778426/1175065)? Anyway i am going with the described code [here](http://ideone.com/OXhVUL) – ravi Dec 08 '12 at 16:32
  • 1
    Well, this code requires an extra library in your project, so you might prefer it if you are already using Guava. Otherwise stick with the straightforward approach that works with plain JDK. – Natix Dec 08 '12 at 16:39
0

Create a multiset and iterate through it pulling out all elements with count 1. O(n).

djechlin
  • 59,258
  • 35
  • 162
  • 290
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);
    }
Achintya Jha
  • 12,735
  • 2
  • 27
  • 39
0

How about creating 2 new Hashsets. Called seenOnce and seenMoreThenOnce.

Then you iterate over all your integers in the different hashmaps.

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.

When you are done iterating over all your hashmaps, seenOnce will contain the integers seen only once.

MTilsted
  • 5,425
  • 9
  • 44
  • 76
-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);
    }
}
Linus Caldwell
  • 10,908
  • 12
  • 46
  • 58