问题
I'm learning lambda right now, and I wonder how can I write this code by a single line with lambda.
I have a Person
class which includes an ID
and name
fields
Currently, I have a List<Person>
which stores these Person
objects. What I want to accomplish is to get a string consisting of person's id just like.
"id1,id2,id3".
How can I accomplish this with lambda?
回答1:
To retrieve a String
consisting of all the ID's separated by the delimiter ","
you first have to map the Person
ID's into a new stream which you can then apply Collectors.joining on.
String result = personList.stream().map(Person::getId)
.collect(Collectors.joining(","));
if your ID field is not a String
but rather an int
or some other primitive numeric type then you should use the solution below:
String result = personList.stream().map(p -> String.valueOf(p.getId()))
.collect(Collectors.joining(","));
回答2:
stream to map, and collect to list!
List<String> myListofPersons = personList.stream()
.map(Person::getId)
.collect(Collectors.toList());
if you need that in a String object then join the list
String res = String.join(" , ", myListStringId);
System.out.println(res);
回答3:
Slightly over-engineered, but helpful to have if this issue occurs more often (especially if you add overloaded methods that delegate to this one using default mappers and separators):
/**
* @param separator used to join the values. NOTE: the separator is interpreted as a regular expression.
* @return a list of the values' string representation according to <code>mapper</code>, separated by the specified
* string. Null if list is null or empty.
*/
public static <R> String toListString(Collection<R> list, String separator,
Function<? super R, ? extends String> mapper)
{
if (list == null || list.isEmpty())
{
return null;
}
return list.stream()
.map(mapper)
.collect(Collectors.joining(separator));
}
and the appropriate inverse funtion:
/**
* @param list a list of values, separated by the specified separator
* @param separator used to join the values. NOTE: the separator is interpreted as a regular expression.
* @param mapper the function to map a single string to a value.
* @return a list of the values. Empty if string is null or empty.
*/
public static <R> List<R> fromListString(String list, String separator,
Function<? super String, ? extends R> mapper)
{
if (list == null || list.isEmpty())
{
return new ArrayList<>();
}
return Arrays.stream(list.trim().split(separator))
.map(mapper)
.collect(Collectors.toCollection(ArrayList::new));
}
If performance is an issue I would opt for the classic loop approach:
StringBuilder s = new StringBuilder();
for(R r : list){
if (s.length() != 0)
s.append(separator);
s.append(mapper.apply(r));
}
return s.toString();
and:
List<R> result = new ArrayList<>();
for (String s : list.trim().split(separator)){
result.add(mapper.apply(s));
}
return result;
回答4:
You can also using Collectors#mapping as below:
String ids = personList.stream().collect(mapping(Person::getId
, Collectors.joining(",")));
OR Person.ID
is not an instance of CharSequence
then you need double mapping as below:
String ids = personList.stream().collect(mapping(Person::getId
, mapping(String::valueOf
, Collectors.joining(","))));
来源:https://stackoverflow.com/questions/44245790/join-a-list-of-objects-properties-into-a-string