Java 8 группировка потоков по свойству без учета регистра - PullRequest
1 голос
/ 20 февраля 2020

У меня есть следующие классы:

LivingPlace:

public class LivingPlace {
    public LivingPlace(String province) {
        this.province = province;
    }

    private String province;

    public String getProvince() {
        return province;
    }
}

Пользователь:

public class User {
    private LivingPlace viv;
    private int age;

    public User(LivingPlace viv, int age) {
        this.viv = viv;
        this.age = age;
    }

    public LivingPlace getLivingPlace() {
        return viv;
    }

    public int getAge() {
        return age;
    }
}

А затем в моем Основном классе у меня есть список пользователей. Я хочу получить количество пользователей в возрасте до 18 лет, сгруппированных по провинциям (зная, что названия провинций каждого пользователя могут содержать любую комбинацию прописных или строчных букв). Я думал что-то вроде:

    Map<String, Integer> rta = users.stream()
            .filter(user -> user.getAge() < 18 && user.getLivingPlace() != null)
            .collect(Collectors.toMap(us -> us.getLivingPlace().getProvince(), Collectors.counting()));

Однако это не скомпилируется.

Есть идеи?

Я получаю несколько ошибок:

* method toMap(Function<? super T,? extends K>, Function<? super T,? extends U>) in the type Collectors is not applicable for the arguments ((<no type> us) -> {}, Collector<Object,?,Long>)
* The method getLivingPlace() is undefined for the type T
* method toMap(Function<? super T,? extends K>, Function<? super T,? extends U>) in the type Collectors is not applicable for the arguments ((<no type> us) -> {}, Collector<Object,?,Long>)

1 Ответ

3 голосов
/ 20 февраля 2020

Для группировки операций вы должны использовать Collectors.groupingBy , потому что Collectors.toMap будет принимать Function в качестве аргументов

Map<String, Long> rta = users.stream().filter(user -> user.getAge() < 18 && user.getLivingPlace() != null)
        .collect(Collectors.groupingBy(us -> us.getLivingPlace().getProvince(), Collectors.counting()));

Как @Holger предлагает, вы можете также используйте Collectors.toMap с функцией слияния, когда ожидается большое количество групп с небольшим количеством

Map<String, Integer> rta = users.stream()
.filter(user -> user.getAge() < 18 && user.getLivingPlace() != null)
.collect(Collectors.toMap(us -> us.getLivingPlace().getProvince(), 
    a -> 1L, Integer::sum));

А если вы хотите выполнить группировку, игнорируя случаи, вы можете преобразовать province в нижний или верхний регистр

Map<String, Long> rta = users.stream().filter(user -> user.getAge() < 18 && user.getLivingPlace() != null)
    .collect(Collectors.groupingBy(us -> us.getLivingPlace().getProvince().toLowerCase(), Collectors.counting()));

или вы можете использовать TreeMap с CASE_INSENSITIVE_ORDER компаратором

Map<String, Long> result = users.stream()
      .filter(user -> user.getAge() < 18 && user.getLivingPlace() != null)
      .collect(Collectors.groupingBy(us -> us.getLivingPlace().getProvince(),
            () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER), Collectors.counting()));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...