Results 1 to 2 of 2
Thread: Does retainAll use equals ?
- 10-27-2008, 04:06 PM #1
Member
- Join Date
- Oct 2008
- Location
- UK
- Posts
- 65
- Rep Power
- 0
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:
The output is: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(); } }
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,
PaulLast edited by Paul Richards; 10-27-2008 at 04:14 PM.
- 10-27-2008, 08:17 PM #2
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.retainAll - removes from this collection all of its elements that are not contained in the specified collection.
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
-
a little problem with (equals)
By gamilah in forum New To JavaReplies: 5Last Post: 10-25-2008, 04:08 AM -
number equals astrisks ????
By nanna in forum New To JavaReplies: 6Last Post: 10-06-2008, 09:47 AM -
Creating a new equals() method help
By Dave0703 in forum New To JavaReplies: 2Last Post: 09-21-2008, 05:32 PM -
Why Equals method should be over ridden in Hashcode?
By skyineyes in forum New To JavaReplies: 1Last Post: 05-26-2008, 04:13 PM -
name clash: equals(E) in and equals(java.lang.Object)
By AdRock in forum New To JavaReplies: 0Last Post: 01-25-2008, 11:13 PM


LinkBack URL
About LinkBacks
Reply With Quote
Bookmarks