bobobear / lambdaj

Automatically exported from code.google.com/p/lambdaj
Apache License 2.0
0 stars 0 forks source link

Method extract fails on LambdaMap values #60

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Execute attached test project with the following test:

@Test
public void testExtractFromMapValues() {
    List<Foo> foos = Arrays.asList(
      new Foo("one", "baz"), 
      new Foo("two", "wiz"), 
      new Foo("three", "baz"));

    Map<String, Foo> map = 
      with(foos)
          .map(on(Foo.class).getCounter());
    Collection<Foo> values = map.values();

    Collection<String> extract =  
          with(values)
              .retain(having(on(Foo.class).getBar(), equalTo("baz")))
              .extract(on(Foo.class).getCounter());

      assertEquals(2, extract.size());   
    }

What is the expected output? What do you see instead?
Test should succeed, expect: collection with two strings: one and three.

Instead, I get an UnsupportedOperationException

What version of the product are you using? On what operating system?
2.3.1, Windows

A workaround is to pass the map values into a new ArrayList, like this:
new ArrayList(map.values())
So I guess it has to do with the fact that the values of a LambdaMap are a 
LambdaCollection.

Original issue reported on code.google.com by dietrich...@gmail.com on 26 Jan 2011 at 7:29

Attachments:

GoogleCodeExporter commented 9 years ago
Applies to 2.3.2 as well.

Original comment by dietrich...@gmail.com on 26 Jan 2011 at 7:51

GoogleCodeExporter commented 9 years ago
Apparently there is an AbstractCollection inside the LambdaCollection which 
throws an UnsupportedOperationException when trying to add something to it. 
Stacktrace:

java.lang.UnsupportedOperationException
        at java.util.AbstractCollection.add(AbstractCollection.java:221)
        at java.util.AbstractCollection.addAll(AbstractCollection.java:305)
        at ch.lambdaj.collection.LambdaCollection.addAll(LambdaCollection.java:135)
        at ch.lambdaj.collection.AbstractLambdaCollection.setInnerCollection(AbstractLambdaCollection.java:46)
        at ch.lambdaj.collection.AbstractLambdaCollection.setInner(AbstractLambdaCollection.java:36)
        at ch.lambdaj.collection.LambdaIterable.doRetain(LambdaIterable.java:100)
        at ch.lambdaj.collection.LambdaCollection.retain(LambdaCollection.java:34)
        at de.escalon.lambdajtests.LambdaMapTest.testExtractFromMapValues(LambdaMapTest.java:28)

It seems there was a similar problem in the past which was solved in 
AbstractLambdaCollection.setInnerCollection(AbstractLambdaCollection.java:46) 
by catching the UnsupportedOperation and creating a LinkedList as 
innerCollection: 

private void setInnerCollection(Collection<? extends T> inner) {
    try {
        ((Collection<T>)innerIterable).clear();
    } catch (UnsupportedOperationException e) { 
        innerIterable = new LinkedList<T>();  
    }     
    ((Collection<T>)innerIterable).addAll((Collection<T>)inner);
}

The question is however, why is add not implemented in the LambdaCollection we 
are using here. Should the fix be a catch-and-create-LinkedList, or should add 
be implemented? Or is this all wrong and the fix must be something else?

Original comment by dietrich...@gmail.com on 26 Jan 2011 at 9:29

GoogleCodeExporter commented 9 years ago
I guess the problem is caused by the list created with: Arrays.asList(...)

For what I know this is an immutable list, so it throws an 
UnsupportedOperationException when you try to add or remove something. Since 
the LambdaCollections are just a wrapper that enriches the original collection 
with the lambdaj features, when you try to modify the LambdaCollection this 
change should be propagated to the inner collection, but in your case this is 
not possible having an immutable collection. 

I will try to find a workaround to this specific case, but in the meanwhile it 
could be great if you could confirm that your use case works as you expect by 
using a normal mutable list, for example created with new ArrayList().

Original comment by mario.fu...@gmail.com on 27 Jan 2011 at 4:04

GoogleCodeExporter commented 9 years ago
Hi Mario,

thank you for looking into this.

I tried a plain-vanilla array list instead of asList() now:
        List<Foo> foos = new ArrayList<Foo>();
        foos.add(new Foo("one", "baz"));
        foos.add( new Foo("two", "wiz"));
        foos.add(new Foo("three", "baz"));
I get an UnsupportedException, too.

Original comment by dietrich...@gmail.com on 27 Jan 2011 at 8:26

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Fixed in release 2.3.3

Original comment by mario.fu...@gmail.com on 24 Apr 2011 at 3:14