7

In C# I can do this:

IEnumerable<long> ids = things.select(x => x.Id);

In Java I have to do this:

Collection<Long> ids = new ArrayList<Long>(things.size());
for(Thing x : things)
   ids.add(x.getId());

Have to do this sort of thing quite a lot now and wonder if there is a more generic way to do this in Java. Could create a method to do it, but then I would have to add an interface with the getId method or something like that... which I can't...

Svish
  • 152,914
  • 173
  • 462
  • 620
  • I assume that `things` does not inherit from Collection or an Array. – Brett Walker Nov 21 '11 at 10:35
  • 1
    Why do you assume that? I loop over `things` using `for`, so have to be either array or iterable at least. – Svish Nov 21 '11 at 11:01
  • @Brett Walker a collection of ids is required, not another collection of things – NimChimpsky Nov 21 '11 at 11:10
  • @Brett I don't want another collection of things, I want a collection of the values of a certain property of things, in this example their ids. – Svish Nov 21 '11 at 11:26
  • What do you want to do with that collection of properites. (Aside:- The type of `this` was not stated.) The specific question may offer different solutions when the larger context is considered. – Brett Walker Nov 21 '11 at 11:30
  • Type of `this` and what I want with it is pretty irrelevant. Asked for general solutions, not specific ones :) – Svish Nov 21 '11 at 12:41

5 Answers5

2

using Guava, specifically the function interface :

public class ThingFunction implements Function<Thing, Long> {
    @Override
    public Long apply(Thing thing) {
        return user.getId();
    }
} 

and invoked like this (where transform is a static import from Collections2 of guava:

Collection<Long> ids = transform(things, new ThingFunction());

Guava has quite a few other benefits too.

Community
  • 1
  • 1
NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
1

Using Apache Commons' BeanUtils and Collections:

Collection<Long> ids = CollectionUtils.collect(things,
        new BeanToPropertyValueTransformer("id"));
Diogo Kollross
  • 368
  • 7
  • 11
0

In Groovy you would only have to do this:

Set ids = things.collect{ aThing -> aThing.Id}

That would give you all the Ids from all the things in Things as a list.

Here is some info on Groovy, and some differences compared to Java

gotomanners
  • 7,808
  • 1
  • 24
  • 39
0

You can try this method. It takes a collection, a method (from the reflection api) and a target class. It invokes the method on all members of the collection and returns a List of the results.

public <T> Collection<T> select(Collection<? extends Object> input, Method getter, Class<T> targetClazz) {
    ArrayList<T> result = new ArrayList<T>();
    for (Object object : input) {
        try {
            Object resultObject = getter.invoke(object, (Object[]) null);
            if (targetClazz.isAssignableFrom(resultObject.getClass())) {
                result.add(targetClazz.cast(resultObject));
            }
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    return result;
}

I ignored proper error handling for now. Usage:

try {

    Method getId = Thing.class.getMethod("getId", null);
    Collection<Long> result = select(things, getId, Long.class);

} catch (SecurityException e) {
    e.printStackTrace();
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}
nfechner
  • 17,295
  • 7
  • 45
  • 64
0

Not really an answer, but you can wait for java 8, which will have lambda expression support. Other than that I think Guava is your best option.

soulcheck
  • 36,297
  • 6
  • 91
  • 90