I have an ArrayList of User objects. Now I need the ArrayList of these user's names only. Is there a way to use toString() on entire ArrayList and convert it to ArrayList of String names rather than doing this in for loop? I have also overridden toString in User class so it returns user's name, and I have tried ArrayList <String> names = usersList.toString() but it didn't work.
4 Answers
You can do this using the Google Collections API:
List<User> userList = ...;
List<String> nameList = Lists.transform(userList, new Function<User, String>() {
public String apply(User from) {
return from.toString(); // or even from.getName();
}
});
The library has been renamed to Guava.
With Java 8, using streams and method references you can now achieve the same thing even without using Guava:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
class User {
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class App {
public static void main(String[] args) {
List<User> users = new ArrayList<>(Arrays.asList(
new User("Alan Turing"),
new User("John von Neumann"),
new User("Edsger W Dijkstra")
));
List<String> names = users
.stream()
.map(User::getName)
.collect(Collectors.toList());
System.out.println(names);
}
}
5 Comments
List<String> nameList = Lists.transform(userList, Functions.toStringFunction());, as long as you stick to toString (instead of the suggested getName).ArrayList<String> to ArrayList<Object[]>ArrayList<String> stringList = ...; ArrayList<Object[]> objectArrayList = Lists.transform(stringList, new Function<String, Object[]>() { public Object[] apply(String from) { return new Object[] { from }; } });The Object#toString() returns a String, not an ArrayList. That's your problem. You really need to loop over it. There's absolutely no reason for an aversion against looping. Just hide it away in some utility method if the code is bothering you somehow ;)
With Java 8, you can use lambda expressions, streams, and method references to simplify your code.
The following
List<User> users = getItSomehow();
List<String> names = new ArrayList<String>();
for (User user : users) {
names.add(user.getName());
}
can then be shortened to like
List<User> users = getItSomehow();
List<String> names = users.stream().map(User::getName).collect(Collectors.toList());
By the way, you can also put the for in a single line:
for (User user : users) names.add(user.getName());
It may however not be directly understandable for starters.
2 Comments
In a word: No. What you need is a map function, which you don't have in Java (yet, as BalusC points out). You can write something similar yourself, but you'll end up iterating over each element in your List regardless.
Comments
public ArrayList< String > toStringList( Collection< MyObject > objectList )
{
ArrayList< String > stringList = new ArrayList< String >();
for( MyObject myobj : objectList ) {
stringList.add( myobj.toString() );
}
return stringList;
}
...
ArrayList< String > myStringList = toStringList( objectList );
There. One line, and you can reuse it with whatever collection of objects you have in the future.