と呼ばれていることを前提と(というか:可能)内蔵を使用しませんgroupBy
の機能です。組み込み関数のセマンティクスには、Foo
オブジェクトで実行する「マージ」操作は含まれません。
代わりに、あなたはCollectors#toMap
機能を使用することがあります。
keyMapper
は、キー、エントリの「識別子」のいくつかの並べ替えを作成する関数です。あなたの場合、これはFoo
を受け取り、Entry<Integer, String>
オブジェクトを作成し、マップのキーとして使用する関数です。 (あなたはそこに任意のPair
かTuple
を使用することができます - でもList<Object>
はそれを行うだろう)
valueMapper
は恒等関数
- することができ
mergeFunction
が、ここで重要なものです:それは同じ番号と文字列を持つ2つのFoo
オブジェクトを(取ります)、残りの値が追加された新しいマージされたFoo
オブジェクトを返します。
結果はMap
になりますが、必要であれば、あなたは、このマップの値からList
を作成することができます。ここで
は一例です:
import static java.util.stream.Collectors.toMap;
import java.util.AbstractMap.SimpleEntry;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
public class GroupByTest
{
public static void main(String[] args)
{
example();
exampleUnmaintainable();
}
private static void example()
{
List<Foo> foos = Arrays.asList(
new Foo(1, "P1", 300, 400),
new Foo(1, "P4", 300, 400),
new Foo(2, "P2", 600, 400),
new Foo(3, "P3", 30, 20),
new Foo(3, "P3", 70, 20),
new Foo(1, "P1", 360, 40),
new Foo(4, "P4", 320, 200),
new Foo(4, "P4", 500, 900)
);
Function<Foo, Entry<Integer, String>> keyMapper = foo ->
new SimpleEntry<Integer, String>(foo.getId(), foo.getS());
Function<Foo, Foo> valueMapper = foo -> foo;
BinaryOperator<Foo> mergeFunction = (f0, f1) ->
new Foo(f0.getId(), f0.getS(), f0.getX()+f1.getX(), f0.getY()+f1.getY());
Map<Entry<Integer, String>, Foo> result =
foos.stream().collect(toMap(keyMapper, valueMapper, mergeFunction));
for (Entry<Entry<Integer, String>, Foo> entry : result.entrySet())
{
System.out.println(entry);
}
}
private static void exampleUnmaintainable()
{
List<Foo> foos = Arrays.asList(
new Foo(1, "P1", 300, 400),
new Foo(1, "P4", 300, 400),
new Foo(2, "P2", 600, 400),
new Foo(3, "P3", 30, 20),
new Foo(3, "P3", 70, 20),
new Foo(1, "P1", 360, 40),
new Foo(4, "P4", 320, 200),
new Foo(4, "P4", 500, 900)
);
List<Foo> result = foos.stream().collect(toMap(
foo -> new SimpleEntry<Integer, String>(foo.getId(), foo.getS()),
foo -> foo, (f0, f1) -> new Foo(f0.getId(), f0.getS(),
f0.getX()+f1.getX(), f0.getY()+f1.getY())))
.values().stream().collect(Collectors.toList());
for (Foo foo : result)
{
System.out.println(foo);
}
}
static class Foo
{
private int id;
private String s;
private int x;
private int y;
public Foo(int id, String s, int x, int y)
{
this.id = id;
this.s = s;
this.x = x;
this.y = y;
}
public int getId()
{
return id;
}
public String getS()
{
return s;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
@Override
public String toString()
{
return "Foo [id=" + id + ", s=" + s + ", x=" + x + ", y=" + y + "]";
}
}
}
うん、パッシブ・アグレッシブ発言:あなたはメソッド名などを好きではない場合、あなたは私達にあなたの実際のFoo
クラスを示している必要があります。私たちはここにちょっと推測するを持っています...
私はhttp://stackoverflow.com/help/how-to-askをお読みください。それは、私たちがあなたを助けてくれる方法で質問を書くのに役立ちます。 – jbrown
@jbrown彼は、 'Foo'sの' ArrayList'を受け入れ、その 'ArrayList'のグループ化されたバージョンを返すメソッドを望んでいます。たとえば、リストのすべての項目を繰り返し処理し、リストに項目がすでに存在するかどうかをチェックします。 –
@nickzoum - リンクされた文書で説明されているように「他の人が問題を再現できるだけのコードを含める」という考え方を導入しています – jbrown