5

I want to add duplicate element in set, what i do? what are the method that i have to override.

    public final class AddDupliacateElementInSet
    {
         public static void main(String[] args)
         {
             Set<Integer> set =new HashSet<>();
             set.add(1);
             set.add(1);
             set.add(3);
             set.add(4);
             set.add(5);
             set.add(6);
             set.forEach(s->System.out.println(s));  
         }
    }
MOHAMMAD WASEEM
  • 51
  • 1
  • 1
  • 5
  • 4
    You can't. That's the point of Set. – Eran Jun 19 '19 at 05:29
  • Sets, by their mathematical definition, _can't_ have duplicates. But, if you tell us more about what you are trying to do, maybe we can help. – Tim Biegeleisen Jun 19 '19 at 05:30
  • You can use a list if you want duplicates. Set was created in first place to have distinct elements – Chaitanya Jun 19 '19 at 05:30
  • I know that the set is not allowing duplicate. But there is some method that they not allowing duplicate element. I want to override these method inside my custom class. – MOHAMMAD WASEEM Jun 19 '19 at 05:33
  • 1
    In that case it's not a set any more, so why not just use a `ArrayList`? – Sweeper Jun 19 '19 at 05:35
  • The answer to your interview question depends on the implementation. In the case of `HashSet`, the set is implemented by a hashmap. For example, the add operation just blindly overwrites the incoming key. So, to make `HashSet` allow duplicates, you would have a bit of reworking to do. – Tim Biegeleisen Jun 19 '19 at 05:40

4 Answers4

6

As community has pointed out in the comments, a Set is not meant to store duplicate values. But for reasons like "interview question" or "library code that you can't change", you can force it to store duplicates by overriding equals to always return false.

For primitives or other objects not under your control, you can create a wrapper class around your value object and make its equals() always return false:

public class UnequalWrapper {

    private int value;

    //...constructor, getter, setter

    @Override
    public boolean equals(Object o) {
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }
}

and then use it:

public static void main(String[] args) {
    UnequalWrapper a = new UnequalWrapper(1);
    UnequalWrapper b = new UnequalWrapper(2);
    UnequalWrapper c = new UnequalWrapper(1);

    Set<UnequalWrapper> set = Set.of(a, b, c);
    set.forEach(wrapper -> System.out.println(wrapper.getValue()));
}

Output:

1
2
1

But again, this is not recommended, do not try this at home!

Edit:
If you are using a wrapper, you can omit equals() and hashcode(). This is because the Object class' methods will check for object reference, which will be different if you are creating a new wrapper instance each time.

Kartik
  • 7,677
  • 4
  • 28
  • 50
2

Any Set implementations in Java Collections don't allow to do that.

Consider using MultiSet from Apache Commons Collections.

import org.apache.commons.collections4.MultiSet;
import org.apache.commons.collections4.multiset.HashMultiSet;

public class Test {
  public static void main(String[] args) {
    MultiSet<Integer> set = new HashMultiSet<>();
    set.add(1);
    set.add(1);
    set.add(3);
    set.add(4);
    set.add(5);
    set.add(6);
    set.forEach(s -> System.out.println(s));
  }
}

Result:

1
1
3
4
5
6
zmag
  • 7,825
  • 12
  • 32
  • 42
  • What is the different between a `MultiSet` and a `List` ? – AxelH Jun 19 '19 at 06:13
  • @AxelH `MultiSet` has methods for the same occurrences. For example, `set.getCount(1)` returns `2` in above case. – zmag Jun 19 '19 at 06:35
  • Ok, I checked, it is not an implementation of `Set`, this is a different `Collection`. The different that's need to be pointed is that `add` always return `true`, so to know if it already exist, you need to check if the `set.getCount` before and after the insertion. With a `Set`, `add()` return false if you insert a duplicate, which is really useful. – AxelH Jun 19 '19 at 08:16
1

From the oracle docs, A set is a collection that contains no duplicate elements. To allow for duplicate elements, you can use Bags or Multisets which are unordered collections that may contain a duplicate element.

You can also get more from this StackOverflow post reasons-for-using-a-bag-in-java

Tony Okoth
  • 157
  • 1
  • 4
0

We can add duplicate elements in a Set as below.

First create a class which contains attributes that we want to put in the HashSet as below.

public class Value {

    int number;
}

After that create any number of instances from this class and assign the values you want to this attribute. Finally, add all instances to the HashSet. Look at the below sample code.

public class JavaApplication22 {

    public static void main(String[] args) {
        Set<Value> numberSet = new HashSet<>();
        Value obj1 = new Value();
        obj1.number = 1;
        Value obj2 = new Value();
        obj2.number = 2;
        Value obj3 = new Value();
        obj3.number = 1;
        Value obj4 = new Value();
        obj4.number = 2;
    
        numberSet.add(obj1);
        numberSet.add(obj2);
        numberSet.add(obj3);
        numberSet.add(obj4);
    
        Iterator<Value> itr = numberSet.iterator();
        while(itr.hasNext()){
            System.out.println(itr.next().number);
        }
    }
}

I think this will work for you.

djm.im
  • 3,295
  • 4
  • 30
  • 45
  • What if we add `equals` and `hashCode` methods to the `Value` class? THen it returns 1, 2. What do you think? – Jack Apr 05 '22 at 06:57