问题
I have a HashSet of Persons. A person has a firstName, lastName and age like: Person("Hans", "Man", 36)
My task is to get a list of the persons who are older than 17, sort them by age and concat the firstName with the lastName like: ["Hans Man","another name", "another name"]
Im just allowed to import:
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.util.List;
import java.util.ArrayList;
My idea was to sort them first, map the names in separate Streams and to zip them, but it doesn't work.
public static void getNamesOfAdultsSortedByAge(Stream<Person> stream){
Stream<Person> result = stream;
Stream<Person> result1 = result.filter(p -> p.getAge() >= 18)
.sorted((x, y) -> Integer.compare(x.getAge(),y.getAge()));
Stream<String> firstName = result1.map(Person::getFirstName);
Stream<String> lastName = result1.map(Person::getLastName);
Stream<String> result3 = concat(firstName, lastName);
List<String> result4 = result3.collect(Collectors.toList());
System.out.println(result4);
}
thank you in advance
回答1:
You could do so using :
public static void getNamesOfAdultsSortedByAge(Stream<Person> stream) {
List<String> sorted = stream.filter(p -> p.getAge() >= 18)
.sorted((x, y) -> Integer.compare(x.getAge(),y.getAge()))
.map(e -> e.getFirstName() + " " + e.getLastName())
.collect(Collectors.toList());
System.out.println(sorted);
}
Here we just map
the sorted stream by concatenating the first name and then the last name, after which we use the .collect()
terminal operation to collect it to a list.
回答2:
This doesn't work:
Stream<String> firstName = result1.map(Person::getFirstName);
Stream<String> lastName = result1.map(Person::getLastName);
After the first map
, the Stream
is of type String
which doesn't fit Person::getLastName
. You need to concat within the first map()
call itself.
回答3:
Inside getNamesOfAdultsSortedByAge
method:
stream
.filter(p -> p.getAge() > 17)
.sorted(Comparator.comparingInt(Person::getAge))
.map(person -> person.getFirstName() + " " + person.getLastName())
.collect(Collectors.toList())
I suppose it should suit your needs. filter
filters people that are only 18 or older, second line sorts given by getAge
predicate, third just maps Person
instance to a string containing %firstName% %lastName%
, and fourth collects the result into a list.
回答4:
I would use the following and as you have strange rules regarding the imports, I hide that one for Comparator deliberately:
List<String> result = stream.filter(p -> p.getAge() >= 18)
.sorted(java.util.Comparator.comparingInt(Person::getAge))
.map(p -> p.getFirstName() + " " + p.getLastName())
.collect(Collectors.toList());
Note: I know of some rules that imply that no other dependency should be used than the one listed on the "allowed list of dependencies", but I've never heard of a rule that only allows to use like 4 imports but disallows one of the most important ones. If Comparator would be an internal interface/class I could understand it, but it's an essential interface. You even use it as a functional interface if you write (x, y) -> Integer.compare(x.getAge(),y.getAge())
, so I really don't get why this import shouldn't be allowed. That being said: my solution does not require you to use an import to java.util.Comparator. Have fun using it. It really makes comparisons easier and less error-prone (just imagine two similarly named methods and you catched the wrong one by mistake... have fun finding that error ;-)).
回答5:
public static void main(String[] args) {
final List<String> matching = Lists.newArrayList(
new Person("Joey", "Tribiani", 28),
new Person("Rachel", "Green", 12),
new Person("Ross", "Geller", 114),
new Person("Chandler", "Bing", 17)).stream()
.filter(person -> person.getAge() > 17)
.sorted(Comparator.comparing(Person::getAge))
.map(person -> person.getFirstName() + " " + person.getLastName())
.collect(toList());
}
If you need to change sorting order just reverse the comparator:
Comparator.comparing(Person::getAge).reversed()
来源:https://stackoverflow.com/questions/53537160/java-streams-zip-two-lists