Какая цель разделения?

Например, если я намереваюсь разбить некоторые элементы, я мог бы сделать что-то вроде:

Stream.of("I", "Love", "Stack Overflow")
      .collect(Collectors.partitioningBy(s -> s.length() > 3))
      .forEach((k, v) -> System.out.println(k + " => " + v));

который выводит:

false => [I]
true => [Love, Stack Overflow]

Но для меня partioningBy есть только подканал groupingBy. Хотя первый принимает параметр Predicate, а последний a Function, я просто вижу раздел как нормальную функцию группировки.

Итак, тот же код делает то же самое:

 Stream.of("I", "Love", "Stack Overflow")
       .collect(Collectors.groupingBy(s -> s.length() > 3))
       .forEach((k, v) -> System.out.println(k + " => " + v));

что также приводит к a Map<Boolean, List<String>>.

Так есть ли какая-то причина, по которой я должен использовать partioningBy вместо groupingBy? Благодаря

Ответы

Ответ 1

partitioningBy всегда будет возвращать карту с двумя записями, одна для которой предикат является истинным, а другой - для того, где он является ложным. Возможно, что обе записи будут иметь пустые списки, но они будут существовать.

Что-то, что groupingBy не будет делать, поскольку оно создает только записи, когда они необходимы.

В крайнем случае, если вы отправляете пустой поток в partitioningBy, вы все равно получите две записи на карте, тогда как groupingBy вернет пустую карту.

РЕДАКТОР. Как упоминалось ниже, это поведение не упоминается в документах Java, однако при его изменении это приведет к добавлению добавленной стоимости partitioningBy. Для Java 9 это уже входит в спецификации.

Ответ 2

partitioningBy немного более эффективен, используя специальную реализацию Map, оптимизированную для того, когда ключ является только boolean.

(Это также может помочь прояснить, что вы имеете в виду: partitioningBy помогает эффективно преодолеть то, что для разделения данных используется логическое условие.)

Ответ 3

метод partitioningBy возвращает карту, ключ которой всегда является логическим значением, но в случае метода groupingBy ключ может быть любого типа объекта

//groupingBy
Map<Object, List<Person>> list2 = new HashMap<Object, List<Person>>();
list2 = list.stream().collect(Collectors.groupingBy(p->p.getAge()==22));
System.out.println("grouping by age -> " + list2);

//partitioningBy
Map<Boolean, List<Person>> list3 = new HashMap<Boolean, List<Person>>();
list3 = list.stream().collect(Collectors.partitioningBy(p->p.getAge()==22));
System.out.println("partitioning by age -> " + list2);

Как вы можете видеть, ключ для карты в случае метода partitioningBy всегда является логическим значением, но в случае метода groupingBy ключ - это тип объекта

Подробный код выглядит следующим образом:

    class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String toString() {
        return this.name;
    }
}

public class CollectorAndCollectPrac {
    public static void main(String[] args) {
        Person p1 = new Person("Kosa", 21);
        Person p2 = new Person("Saosa", 21);
        Person p3 = new Person("Tiuosa", 22);
        Person p4 = new Person("Komani", 22);
        Person p5 = new Person("Kannin", 25);
        Person p6 = new Person("Kannin", 25);
        Person p7 = new Person("Tiuosa", 22);
        ArrayList<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);
        list.add(p5);
        list.add(p6);
        list.add(p7);

        // groupingBy
        Map<Object, List<Person>> list2 = new HashMap<Object, List<Person>>();
        list2 = list.stream().collect(Collectors.groupingBy(p -> p.getAge() == 22));
        System.out.println("grouping by age -> " + list2);

        // partitioningBy
        Map<Boolean, List<Person>> list3 = new HashMap<Boolean, List<Person>>();
        list3 = list.stream().collect(Collectors.partitioningBy(p -> p.getAge() == 22));
        System.out.println("partitioning by age -> " + list2);

    }
}