たとえば、いくつかの要素を分割する場合は、次のようにします。
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
をパラメーターとして受け入れますが、後者はFunction
をパラメーターとして受け入れますが、パーティションを通常のグループ化関数と見なしています。
したがって、同じコードはまったく同じことを行います。
Stream.of("I", "Love", "Stack Overflow")
.collect(Collectors.groupingBy(s -> s.length() > 3))
.forEach((k, v) -> System.out.println(k + " => " + v));
これもMap<Boolean, List<String>>
になります。
では、partioningBy
の代わりにgroupingBy
を使用する必要がある理由はありますか?ありがとう
partitioningBy
は常に、2つのエントリを持つマップを返します。1つは述語が真である場所、もう1つは偽である場所です。両方のエントリに空のリストが含まれる可能性がありますが、それらは存在します。
これは、必要なときにのみエントリを作成するため、groupingBy
が実行しないことです。
極端な場合、空のストリームをpartitioningBy
に送信すると、マップには2つのエントリが取得されますが、groupingBy
は空のマップを返します。
編集:以下で説明するように、この動作はJavaのドキュメントには記載されていませんが、変更すると、現在追加されている値partitioningBy
が失われます。Java 9これはすでに仕様に含まれています。
partitioningBy
は、キーが単なるMap
である場合に最適化された特別なboolean
実装を使用して、少し効率的です。
(また、あなたの意味を明確にするのに役立つかもしれません。partitioningBy
は、データを分割するために使用されるブール条件があることを効果的に理解するのに役立ちます。)
groupingBy
とpartitioningBy
のもう1つの違いは、前者は_Function<? super T, ? extends K>
_を受け取り、後者は_Predicate<? super T>
_を取ることです。
メソッド参照またはs -> s.length() > 3
などのラムダ式を渡すと、これらの2つのメソッドのいずれかで使用できます(コンパイラーは、選択したメソッドで必要なタイプに基づいて、機能インターフェイスタイプを推測します)。
ただし、_Predicate<T>
_インスタンスがある場合は、Collectors.partitioningBy()
にのみ渡すことができます。 Collectors.groupingBy()
では受け入れられません。
同様に、_Function<T,Boolean>
_インスタンスがある場合は、Collectors.groupingBy()
にのみ渡すことができます。 Collectors.partitioningBy()
では受け入れられません。
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);
}
}