Retrieving a List of Elements from an ArrayList

Say I have a bean as shown below.

class Customer{ private String code; private String name; private Integer value; //getters setters omitted for brevity } 

Then from the method, I get a List<Customer> back. Now let me say that I want to get a list of all the member names from the list. Obviously, I can go through and build the List<String> name element myself.

However, I was wondering if there is a short way or a more efficient way of this technique that anyone knows. For example, if I want to get a list of all the keys in a Map object, I get the map.keySet () command. I’m trying to find out something along this line.

+6
java arraylist
source share
8 answers

Guava has Lists.transform , which can convert List<F> to List<T> using the provided Function<F,T> (or rather, Function<? super F,? extends T> ).

From the documentation:

 public static <F,T> List<T> transform( List<F> fromList, Function<? super F,? extends T> function ) 

Returns a list that function applies to each fromList element. The returned list is a transformed view fromList ; changes in fromList will be reflected in the returned list and vice versa.

function is applied lazily, called if necessary.

Similar real-time conversions are also provided as follows:

+6
source share

It looks like you are looking for the Java equivalent of Perl map . Such things can be added to the collection library once (if) Java receives a closure. Until then, I think this is the best you can do:

 List<String> list = new ArrayList<String>(customers.size()); for ( Customer c : customers ) { list.add(c.getName()); } 

You can also write a map function that uses a simple interface to provide a map function. Something like that:

 public interface Transform<I, O> { O transform(I in); } public <I, O> List<O> map(Collection<I> coll, Transform<? super I, ? extends O> xfrm) { List<O> list = new ArrayList<O>(coll.size()); for ( I in : coll ) { list.add(xfrm.transform(in)); } return list; } 
+5
source share

might use something like this: http://code.google.com/p/lambdaj/

+4
source share

I think this is what you will need to code yourself, in a loop.

+3
source share

You can use LambdaJ Converter and have the following line:

 List<String> customerNames = convert(customerList, new Converter<Customer,String>() { public String convert(Customer customer) { return customer.getName(); } }); 
+2
source share

You need to use a loop, but the function you are looking for is called map in functional languages. It is possible to implement map in Java, although it tends to be rather inelegant; here is the version that I implemented many centuries ago in my "Java material should be, but for some reason does not exist":

 public interface MapFunction<T, U> { public U map(T source); } public static <T, U> U[] map(T[] objects, MapFunction<T, U> f) { if(objects.length == 0) {throw new IllegalArgumentException("Can't map onto an empty array");} @SuppressWarnings("unchecked") U[] rtn = (U[])Array.newInstance(f.map(objects[0]).getClass(), objects.length); for(int i = 0; i < objects.length; i++) rtn[i] = f.map(objects[i]); return rtn; } 

Using this, you can do:

 List<Customer> list = yourFunction(); List<String> names = Arrays.asList(map(list.toArray(new Customer[0]), new MapFunction<Customer, String>() { public String map(Customer c) { return c.getName(); } })); 

You can naturally modify the map to collect collections instead of arrays, which eliminates the need for Arrays.asList and List.toArray

+2
source share

Using Guava , you can use Function along with Iterables.transform , Collections2.transform or Lists.transform to create an Iterable , Collection or List respectively.

 Iterable<String> names = Iterables.transform(customers, new Function<Customer, String>() { public String apply(Customer from) { return from.getName(); } }); 

Iterable returns lazy and applies the function to the base list when you execute it. For a List<String> containing names, you can use:

 List<String> names = Lists.transform(...); 

or

 ImmutableList<String> names = ImmutableList.copyOf(Iterables.transform(...)); 

Of course, writing out an anonymous internal implementation of the Function class every time you want to do this is ugly and verbose, so you can make the Function constant available from the Customer class called Customer.NAME for example.

Then the conversion looks much nicer (especially using static imports):

 for (String name : transform(customers, Customer.NAME)) { ... } 

I also wrote about using interfaces for specific properties of objects (e.g. name here) to help consolidate such functions on my blog here .

+2
source share

.... is there a shorter or more efficient way

So you are looking for a more efficient way to do this:

  List<String> names = new ArrayList<String>(); for( Customer customer : yourCustomerList ) { names.add( customer.getName() ); } 

? !!!!

Or just another way?

All previous answers are not more efficient in terms of runtime and coding. They are, however, more flexible.

Another alternative might be to include Scala Groovy in your Java code and use this:

list.map( _.name ) hit>

 list.collect { it.name } 

If compiled, Groovy classes can be used with Java, or you can connect them as a script.

Here's a sample for this Customer class, using Groovy as a script.

  List<Customer> customers = Arrays.asList( new Customer[]{ new Customer("A","123",1), new Customer("B","456",2), new Customer("C","789",3), new Customer("D","012",4) }); setVariable(customers, "list"); evaluate("names = list.collect { it.name } "); List<String> names = (List<String>) getVariable("names"); System.out.println("names = " + names); 

Output:

 names = [A, B, C, D] 

note: I extracted the method for readability, but you can see them below

But again, this is just different, no more effective than regular for the cycle.

Here is the complete source code . To run, you just need Java1.6 and Groovy in the classpath.

+1
source share

All Articles