Results 1 to 2 of 2
  1. #1
    Paul Richards is offline Member
    Join Date
    Oct 2008
    Location
    UK
    Posts
    65
    Rep Power
    0

    Default Does retainAll use equals ?

    Hi,

    I have a LinkedHashMap which has strings as its keys and objects of my own class as the values. I want to remove all entries from this map where the values are not present in a set that I pass to it. The natural choice seemed to me to use the values() method to get the set of values, and use retainAll. However, I am finding that my LinkedHashMap is empty!

    I have prepared some much simpler code that illustrates the same problem:
    Java Code:
    import java.awt.geom.Point2D;
    import java.util.HashSet;
    import java.util.LinkedHashMap;
    
    public class RetainAllTester {
        public RetainAllTester() {
            test1();
            test2();
            test3();
            test4();
        }
            
        private void test1() {
            LinkedHashMap<Integer, Data> test = new LinkedHashMap<Integer, Data>();
            Data d1 = new Data(10);
            Data d2 = new Data(20);
            Data d3 = new Data(30);
            test.put(1, d1);
            test.put(2, d2);
            test.put(3, d3);
            //
            HashSet<Data> sub = new HashSet<Data>();
            sub.add(d3);
            sub.add(d1);
            System.out.println("Test 1:");
            System.out.println(test);
            test.values().retainAll(sub);
            System.out.println(test);
        }
        
        private void test2() {
            LinkedHashMap<Integer, String> test = new LinkedHashMap<Integer, String>();
            test.put(1, "a");
            test.put(2, "b");
            test.put(3, "c");
            //
            HashSet<String> sub = new HashSet<String>();
            sub.add("c");
            sub.add("a");
            System.out.println("Test 2:");
            System.out.println(test);
            test.values().retainAll(sub);
            System.out.println(test);
        }
        
        private void test3() {
            LinkedHashMap<Integer, Integer> test = new LinkedHashMap<Integer, Integer>();
            test.put(1, 10);
            test.put(2, 20);
            test.put(3, 30);
            //
            HashSet<Integer> sub = new HashSet<Integer>();
            sub.add(30);
            sub.add(10);
            System.out.println("Test 3:");
            System.out.println(test);
            test.values().retainAll(sub);
            System.out.println(test);
        }
        
        private void test4() {
            LinkedHashMap<Integer, Data> test = new LinkedHashMap<Integer, Data>();
            test.put(1, new Data(10));
            test.put(2, new Data(20));
            test.put(3, new Data(30));
            //
            HashSet<Data> sub = new HashSet<Data>();
            sub.add(new Data(30));
            sub.add(new Data(10));
            System.out.println("Test 4:");
            System.out.println(test);
            test.values().retainAll(sub);
            System.out.println(test);
        }
        
        private class Data {
            private int i;
            public Data(int i) {
                this.i = i;
            }
            public String toString() {
                return Integer.toString(i);
            }
            public boolean equals(Object o) {
                System.out.println("EQUALS METHOD BEING CALLED");
                if(o instanceof Data) {
                    Data other = (Data) o;
                    return i==other.i;
                }
                else {
                    return false;
                }
            }
        }
        
        public static void main(String[] args) {
            new RetainAllTester();
        }
    }
    The output is:

    Test 1:
    {1=10, 2=20, 3=30}
    {1=10, 3=30}
    Test 2:
    {1=a, 2=b, 3=c}
    {1=a, 3=c}
    Test 3:
    {1=10, 2=20, 3=30}
    {1=10, 3=30}
    Test 4:
    {1=10, 2=20, 3=30}
    {}



    The results of test1, test2 and test3 are as I expected.

    However, the outcome of test4 is the same as in my real program. Is this because retainAll is using == instead of equals() ? Or, have I gone completely mad and made a silly mistake somewhere...

    Regards,

    Paul
    Last edited by Paul Richards; 10-27-2008 at 04:14 PM.

  2. #2
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    17,565
    Rep Power
    25

    Default

    retainAll - removes from this collection all of its elements that are not contained in the specified collection.
    From the API specs. That seems to say the elements are tested to be the same, not their contents the same. Ie == would be the test to see if they are the same.

    Your other tests work because of JVM optimization/reuse on immutable objects like String and Integer.

    Seems its not like I thought. When you change equals() you must also change hashCode()
    Here's what I tried.
    Java Code:
    import java.awt.geom.Point2D;
    import java.util.HashSet;
    import java.util.LinkedHashMap;
    
    public class RetainAllTester {
        boolean showCaller = true; //false;
          
        public RetainAllTester() {
            test1();
            test2();
            test3();
            test4();
            Integer i1 = new Integer(1);
            Integer i2 = new Integer(1);
            System.out.println("test == " + (i1==i2)); //test == false
        }
            
        private void test1() {
            LinkedHashMap<Integer, Data> test = new LinkedHashMap<Integer, Data>();
            Data d1 = new Data(10);
            Data d2 = new Data(20);
            Data d3 = new Data(30);
            test.put(1, d1);
            test.put(2, d2);
            test.put(3, d3);
            //
            HashSet<Data> sub = new HashSet<Data>();
            sub.add(d3);
            sub.add(d1);
            System.out.println("Test 1:");
            System.out.println(test);
            test.values().retainAll(sub);
            System.out.println(test);
        }
        
        private void test2() {
            LinkedHashMap<Integer, String> test = new LinkedHashMap<Integer, String>();
            test.put(1, "a");
            test.put(2, "b");
            test.put(3, "c");
            //
            HashSet<String> sub = new HashSet<String>();
            sub.add("c");
            sub.add("a");
            System.out.println("Test 2:");
            System.out.println(test);
            test.values().retainAll(sub);
            System.out.println(test + ", sub=" + sub);
        }
        
        private void test3() {
            LinkedHashMap<Integer, Integer> test = new LinkedHashMap<Integer, Integer>();
            Integer i10 = new Integer(10);  //<<<
            test.put(1, i10);
            test.put(2, 20);
            test.put(3, 30);
            //
            HashSet<Integer> sub = new HashSet<Integer>();
            sub.add(30);
            sub.add(10);
            System.out.println("Test 3:");
            System.out.println("B:" + test); //B:{1=10, 2=20, 3=30}
            test.values().retainAll(sub);
            System.out.println("A:" + test + " , sub=" + sub);//A:{1=10, 3=30} , sub=[10, 30]
            java.util.Iterator it = sub.iterator();
            Object obj = it.next(); //                                          false
            System.out.println("it0= " + obj + " " + obj.getClass() + " " + (i10 == obj)
                               + " " + i10.equals(obj));  // this is true
               //it0= 10 class java.lang.Integer false true
        }
        
        private void test4() {
            showCaller = true;             // turn on tracing
            LinkedHashMap<Integer, Data> test = new LinkedHashMap<Integer, Data>();
            test.put(1, new Data(10));
            test.put(2, new Data(20));
            test.put(3, new Data(30));
            //
            HashSet<Data> sub = new HashSet<Data>();
            sub.add(new Data(30));
            sub.add(new Data(10));
            System.out.println("Test 4:");
            System.out.println("Before:" + test);
            System.out.println("test.values()= " + test.values());
            test.values().retainAll(sub);   
            //retainAll - removes from this collection all of its elements that are not contained in
            // the specified collection. 
            System.out.println("After:" + test + ", sub=" + sub);
            //After:{1=10, 3=30}, sub=[10, 30]    <<< with hashCode override<<<<<<<<<<
        }
        
        //-------------------------------------------------------------
        private class Data {
            private int i;
            public Data(int i) {
                this.i = i;
            }
            public String toString() {
                return Integer.toString(i);
            }
            @Override
            public boolean equals(Object o) {
                System.out.println("EQUALS METHOD BEING CALLED"); // NOT CALLED???
                if(o instanceof Data) {
                    Data other = (Data) o;
                    return i==other.i;
                }
                else {
                    return false;
                }
            }
            int k = 123;
            @Override
            public int hashCode() {
             if(showCaller) {
    //            try{throw new Exception("Who called k=" + k);}catch(Exception x) {x.printStackTrace();}
                return k+i;    // very simple to correspond with equals
             }
             return super.hashCode();
            }
        } // end class Data
        
        public static void main(String[] args) {
            new RetainAllTester();
        }
    }
    Last edited by Norm; 10-27-2008 at 08:57 PM.

Similar Threads

  1. a little problem with (equals)
    By gamilah in forum New To Java
    Replies: 5
    Last Post: 10-25-2008, 04:08 AM
  2. number equals astrisks ????
    By nanna in forum New To Java
    Replies: 6
    Last Post: 10-06-2008, 09:47 AM
  3. Creating a new equals() method help
    By Dave0703 in forum New To Java
    Replies: 2
    Last Post: 09-21-2008, 05:32 PM
  4. Why Equals method should be over ridden in Hashcode?
    By skyineyes in forum New To Java
    Replies: 1
    Last Post: 05-26-2008, 04:13 PM
  5. Replies: 0
    Last Post: 01-25-2008, 11:13 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •