7

Suppose I have an object that looks like:

public class Obj {
String foo;
String bar;
}

If I create an arraylist of type Obj and populate it, is there a way I can return a list of all the objects in the array's foo attribute from the ArrayList?

EDIT: I should have been more clear, I did not want to do this via iteration

1
  • You have List<Obj> objs and want to create a second list from that List<String> that contains the foo attribute of all the Obj from objs? Commented Jan 26, 2011 at 17:08

6 Answers 6

10

Try this:

Collection<String> names = CollectionUtils.collect(personList, TransformerUtils.invokerTransformer("getName"));  

Use apache commons collection api.

Sign up to request clarification or add additional context in comments.

Comments

7

You'll have to iterate through your List<Obj> and collate the foo entries into a new List

e.g.

List<String> foos = new ArrayList<String>();
for (Obj obj : objs) {
  foos.add(obj.foo)
}

or for Java 8 and beyond, use streams thus:

objs.stream().map(o -> o.foo).collect(toList());

3 Comments

my first version was goign to be this: var foos = objs.Select( x=>x.foo); until i realized it was a java question. Damn you LINQ goodness!
You can do the equivalent of map in plain Java using something like Guava. There's (a bit) more work involved obviously, but it has advantages over allocating memory for a copy of all the foo values in the original list.
Does Java 8 Lambda provide any new cleverness for this? Ala the scala-LINQ trickery.
4

Using Guava you could create a view of the foo property of the objects in the List using Lists.transform like this:

public class Obj {
  String foo;
  String bar;

  public static final Function<Obj, String> FOO = new Function<Obj, String>() {
    public String apply(Obj input) {
      return input.foo;
    }
  };
}

public void someMethod(List<Obj> objs) {
  List<String> foos = Lists.transform(objs, Obj.FOO);
  ...
}

Unlike other solutions, this is purely a view of the List<Obj> and as such it doesn't allocate a whole separate ArrayList or some such in memory and can be created in almost no time regardless of the size of your List<Obj>. Additionally, if you change the original List<Obj>, the foos list will reflect that change.

In Java 8 (due in 2012 sometime), this will become a lot easier with lambda expressions and method references. You'll be able to do something like this:

List<Obj> objs = ...
List<String> foos = objs.map(#Obj.getFoo);

Comments

1

The answer of @Surodip uses a compact solution based on Apache Commons Collections. But that solution is not typesafe, since the Transfomer references the property via string expression: TransformerUtils.invokerTransformer("getName")

Here is a more verbose, but typesafe solution using Apache Commons Collections:

Collection<String> values = CollectionUtils.collect(messages, new Transformer<Obj, String>(){

            @Override
            public String transform(Obj input) {
                return input.getFoo();
            }

        });

The above solutions uses Apache Commons Collection Version >= 4, which supports generics for type safety.

Below is the less typesafe version for Apache Collections Version < 4, which does not use generics:

Collection values = CollectionUtils.collect(messages, new Transformer(){

            @Override
            public Object transform(Object input) {
                Obj obj = (Obj) input;
                return obj.getFoo();
            }

        });

Comments

0

Iterate through the list and create a Set of all foo properties.

Comments

0

something like this?

List<String> foos = new ArrayList<String>();
for (Obj obj : objList )
{
    foos.addElement(obj.foo);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.