commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Greg Zoller <g...@codaware.com>
Subject Re: Question about CollectionUtils semantics
Date Mon, 27 Jan 2003 23:56:08 GMT
Peter...

I think the reason your example works is that you're using String-typed 
variables.
I think the JVM might cache static references to strings, i.e. not 
create duplicate
objects in memory for strings having the same text value.  If that's 
right, then
you're really not comparing two objects with equals() behavior, but one real
object with == behavior, which is why I think it worked.

I have another example that uses another object:

// Simple Object that implements equals()
public class Hey {
    private String id;
    public Hey( String id ) { this.id = id; }
    public boolean equals( Object obj ) {
        System.out.println("--- Hey.equals() called!");
        Hey otherHey = (Hey) obj;
        if( otherHey.id.equals( this.id ) )
            return true;
        return false;
    }
    public String toString() { return id; }
}


// Example
import org.apache.commons.collections.*;
import java.util.*;

public class Test {
    public static void main( String[] args ) {
        Hey objOne = new Hey("one");
        Hey objTwo = new Hey("two");
        Hey objThree = new Hey("three");
        Hey objA = new Hey("a");
        Hey objB = new Hey("b");
        Hey objC = new Hey("c");
        Hey extra = new Hey("two");  // another object functionally 
equivalent to objTwo

        ArrayList listOne = new ArrayList();
        ArrayList listTwo = new ArrayList();

        listOne.add( objOne );
        listOne.add( objTwo );
        listOne.add( objThree );

        listTwo.add( objA );
        listTwo.add( objB );
        listTwo.add( objC );
        listTwo.add( extra );

        // Commons Way
        System.out.println("=== 
org.apache.commons.collections.CollectionUtils ===");
        Collection intsec = CollectionUtils.intersection( listOne, 
listTwo );
        System.out.println("Number of objects in intersection: " + 
intsec.size());

        // java.util approach
        System.out.println("=== java.util.Collection ===");
        listOne.retainAll( listTwo );
        System.out.println("Number of objects in intersection: " + 
listOne.size());
    }
}


Here's the result:

=== org.apache.commons.collections.CollectionUtils ===
Number of objects in intersection: 0
=== java.util.Collection ===
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
--- Hey.equals() called!
Number of objects in intersection: 1

Note that when I tried CommonUtils.intersection() none was found, and
neither was Hey.equals().  If equals() had been called 'objTwo' and 'extra'
would have been found to be equivalent.  When I use 
java.util.Collection.retainAll()
I get the result I expected since this implementation does in fact call
equals().

This is the difference in behavior that I was referring to.  Whether or not
this is a bug or feature I leave to others. :-)

Regards,
Greg


Peter Ko├ček wrote:

>----- Original Message -----
>From: "Greg Zoller"
>  
>
>>I have a question about some CollectionUtils methods that operate
>>semantically diferently
>>from the java.util.Collection methods they are augmenting.
>>The java.util.Collection methods use equals() when doing set operations
>>(retainAll(), etc.).
>>Because it appears to be implemented largely using HashMap gets for
>>cardinality counting,
>>CollectionUtils methods such as intersection() behave according to
>>object comparision
>>using == not equals().
>>    
>>
>
>I live in hope that CollectionUtils behaves as equivalent as possible to
>java.util.Collection . Given two collections
>
>        Collection _c = new ArrayList();
>        _c.add(("a").toUpperCase());
>        _c.add("X");
>        Collection _d = new LinkedList();
>        _d.add(("a").toUpperCase());
>        _d.add("Y");
>
>what should be the intersection of them both? I would suggest a collection
>containing one element "A". Do you agree? I have derived a snippet from the
>CollectionUtils test cases to show that.
>
>-peter
>
>-------------------------
>
>import java.util.*;
>import org.apache.commons.collections.CollectionUtils;
>
>public class TestCollectionUtils {
>    public TestCollectionUtils(String testName) {
>        System.out.println("And now we test feature " + testName + ".");
>        setUp();
>    }
>
>    public static void main(String args[]) {
>      TestCollectionUtils aTest = new TestCollectionUtils("testIntersection");
>      aTest.testIntersection();
>      System.out.println("OK - End of test");
>    }
>
>    private Collection _a = null;
>    private Collection _b = null;
>    private Collection _c = null;
>    private Collection _d = null;
>
>    public void setUp() {
>        _a = new ArrayList();
>        _a.add("a");
>        _a.add("b");
>        _a.add("b");
>        _a.add("c");
>        _a.add("c");
>        _a.add("c");
>        _a.add("d");
>        _a.add("d");
>        _a.add("d");
>        _a.add("d");
>        _b = new LinkedList();
>        _b.add("e");
>        _b.add("d");
>        _b.add("d");
>        _b.add("c");
>        _b.add("c");
>        _b.add("c");
>        _b.add("b");
>        _b.add("b");
>        _b.add("b");
>        _b.add("b");
>        _c = new ArrayList();
>        _c.add(("a").toUpperCase());
>        _c.add("X");
>        _d = new LinkedList();
>        _d.add(("a").toUpperCase());
>        _d.add("Y");
>    }
>
>    public void assertNull(Object o) {
>      if (o != null) throw new RuntimeException("assertNull: " + o.toString() +
>" should be null, but it isn't.");
>    }
>    public void assertEquals(Object o1, Object o2) {
>      if (o1 == null && o2 == null) return;
>      if (o1 == null) throw new RuntimeException("assertEquals: The first object
>is null, and " + o2.toString() + " isn't.");
>      if (!(o1.equals(o2))) throw new RuntimeException("assertEquals: " +
>o1.toString() + " isn't equal to " + o2);
>    }
>    public void assertIdentity(Object o1, Object o2) {
>       if (o1 != o2) throw new RuntimeException("assertIdentity: " + o1 + " is
>not identical with " + o2);
>    }
>    public void assertDifference(Object o1, Object o2) {
>       if (o1 == o2) throw new RuntimeException("assertDifference: " + o1 + " is
>identical with " + o2);
>    }
>
>    public void testIntersection() {
>        Collection col = CollectionUtils.intersection(_a,_b);
>        Map freq = CollectionUtils.getCardinalityMap(col);
>        assertNull(freq.get("a"));
>        assertEquals(new Integer(2),freq.get("b"));
>        assertEquals(new Integer(3),freq.get("c"));
>        assertEquals(new Integer(2),freq.get("d"));
>        assertNull(freq.get("e"));
>        Collection col2 = CollectionUtils.intersection(_b,_a);
>        Map freq2 = CollectionUtils.getCardinalityMap(col2);
>        assertNull(freq2.get("a"));
>        assertEquals(new Integer(2),freq2.get("b"));
>        assertEquals(new Integer(3),freq2.get("c"));
>        assertEquals(new Integer(2),freq2.get("d"));
>        assertNull(freq2.get("e"));
>
>        assertEquals("A", "A");
>        assertEquals("A" + "B", "A" + "B");
>        assertIdentity("A" + "B", "A" + "B");
>        assertEquals(("A" + "B").toLowerCase(), ("A" + "B").toLowerCase());
>        assertDifference(("a").toUpperCase(), ("a").toUpperCase());
>
>        System.out.println("We create the string A via method call to get
>different objects.");
>
>        Collection col3 = CollectionUtils.intersection(_c,_d);
>
>        Map freq_c = CollectionUtils.getCardinalityMap(_c);
>        Map freq_d = CollectionUtils.getCardinalityMap(_d);
>        System.out.println("frequency of A in _c: " + freq_c.get("A"));
>        System.out.println("frequency of A in _d: " + freq_d.get("A"));
>        Map freq3 = CollectionUtils.getCardinalityMap(col3);
>        System.out.println("frequency of A in intersection(_c, _d): " +
>freq3.get("A"));
>        assertEquals(new Integer(1),freq3.get("A"));
>        assertEquals(new Integer(1), new Integer(col3.size()));
>        System.out.println("The intersection between _c and _d is " +
>col3.iterator().next());
>    }
>}
>  
>




Mime
View raw message