Допустим, у меня есть документ, который выглядит так:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class main {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("New York", "foo", "bar"),
new Person("New York", "bar", "foo"),
new Person("New Jersey", "foo", "bar"),
new Person("New Jersey", "bar", "foo")
);
}
public static class Person {
public String city;
public String firstName;
public String lastName;
Person(String city, String firstName, String lastName) {
this.city = city;
this.firstName = firstName;
this.lastName = lastName;
}
}
}
Как я могу использовать потоки, чтобы получить только одного человека из каждого города и вернуть его в список?
Вы можете собрать записи на карту, используя Person::getCity, а затем сопоставить значения записей и получить первое.
import java.util.*;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;
public class App {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("New York", "foo", "bar"),
new Person("New York", "bar", "foo"),
new Person("New Jersey", "foo", "bar"),
new Person("New Jersey", "bar", "foo"));
List<Person> firstByCity = groupBy(people, Person::getCity)
.entrySet().stream()
.map(e -> e.getValue().get(0))
.collect(Collectors.toList());
System.out.println(firstByCity);
}
// Source: https://stackoverflow.com/a/75377044/1762224
public static <E, K, V> Map<K, List<V>> groupBy(
Collection<E> collection, Function<E, K> keyFn, Function<E, V> valueFn) {
return collection.stream()
.map(item -> new SimpleEntry<K, V>(keyFn.apply(item), valueFn.apply(item)))
.collect(Collectors.groupingBy(Entry::getKey,
Collectors.mapping(Entry::getValue, Collectors.toList())));
}
public static <E, K> Map<K, List<E>> groupBy(Collection<E> collection, Function<E, K> keyFn) {
return groupBy(collection, keyFn, Function.identity());
}
public static class Person {
public String city;
public String firstName;
public String lastName;
Person(String city, String firstName, String lastName) {
this.city = city;
this.firstName = firstName;
this.lastName = lastName;
}
public String getCity() {
return city;
}
@Override
public String toString() {
return String.format("{ city: %s, firstName: %s, lastName: %s }",
city, firstName, lastName);
}
}
}
[
{ city: New York, firstName: foo, lastName: bar },
{ city: New Jersey, firstName: foo, lastName: bar }
]