0

Why does containsAll method on a HashSet does not remain consistent if remove is called on the Set whereas a containsValue method on a HashMap remains consistent after a value is removed After a value is removed from a HashSet containsAll returns false even if all values were present where as in case of HashMap the containsValue method returns correct value

public static void main(String[] args)
    {

    HashSet<String> lookup=new HashSet<String>();
    HashMap<Integer,String> findup=new HashMap<Integer,String>();

    String[] Alltokens={"This","is","a","programming","test","This","is","a","any","language"};
    for(String s:Alltokens)
        lookup.add(s);

    String[] tokens={"This","is","a"};
    Collection<String> tok=Arrays.asList(tokens);

    lookup.remove(Alltokens[5]); 
     if(lookup.containsAll(tok))
       System.out.print("found");
    else    
        System.out.print("NOT found");

    Integer i=0;
    for(String s:Alltokens)
        findup.put(i++,s);
    boolean found=true;
    findup.remove(Alltokens[0]);
        findup.remove(5);               //Edit : trying to remove value whose key is 5
    for(String s:tokens)
        if(!findup.containsValue(s))
            found=false;
    System.out.print("\nIn map " + found);
}

Output NOT found In map true

Is there a way to keep containsAll consistent if remove method is called on the HashSet? Also if a value that was not present in the set is passed to remove method.ContainsAll remains consistent

        lookup.remove("Alltokens[5]");
    if(lookup.containsAll(tok))

//This will be true now where as it is false if a value already present is removed

May be it has got to do something with keys in HashMaps and no keys in HashSet.Can you please explain how do they work?

rakesh99
  • 1,234
  • 19
  • 34
  • There's something missing after `lookup.remove(Alltokens[5]);`. – Joachim Sauer Nov 12 '12 at 07:54
  • The above code will not compile. You should post the actual code, and you should add `{ }` rather than allowing one-line statements to cause these issues for you, as you refactor your code and they change from one-liners to multi-liners. – pickypg Nov 12 '12 at 07:55
  • @JoachimSauer Sorry the if condition went missing.edited it now – rakesh99 Nov 12 '12 at 08:18

1 Answers1

5

Map.remove(Object) removes a mapping based on the key.

Since you use Integer objects as the keys (put(i++, s)) you will remove nothing when you call findup.remove(Alltokens[0])! Check its return value to see that it will return false.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • I changed it to findup.remove(5) even then it returns true.Moreover how would this figured out if i have passed a key or a value.If the method takes a key as an argument won't it have tried to convert a string to an integer in the case findup.remove(Alltokens[0]) – rakesh99 Nov 12 '12 at 08:05
  • 1
    1.) 5="This" and "This" is contained twice in your map: once at 0, once at 5. So even after you removed 5, "This" is still contained in the values of the map and 2.) No, a `String` is simply never `equal` to an `Integer`, so it will just never remove anything. Java doesn't do automagic type conversion for you, most of the time. – Joachim Sauer Nov 12 '12 at 08:12
  • And in case of a HashSet after Alltokens[5] is removed since it doesn't contain duplicates 'This' is no more there and it returns false.But why doesn't findup.remove(Alltokens[0]) give an error.Isn't it an error to pass a string to a function which takes an integer? – rakesh99 Nov 12 '12 at 08:24
  • 1
    The reason that compiles is that `remove()` accepts an `Object`, no matter what the key type is. The [reason is complicated](http://stackoverflow.com/questions/857420/what-are-the-reasons-why-map-getobject-key-is-not-fully-generic) and *most of the time* it's an error to pass in something that's not of the type of your key, but unfortunately that decision is fixed and can't easily be changed. – Joachim Sauer Nov 12 '12 at 08:30