Wenn Ihre Absicht, eine solche „besondere“ Gruppierung zu tun ist, sollten Sie (oder besser gesagt: kann) nicht den eingebauten verwenden in groupBy
Funktion. Die Semantik der integrierten Funktion enthält nicht die Operation "Zusammenführen", die Sie für die Objekte Foo
ausführen möchten.
Stattdessen können Sie die Collectors#toMap
Funktion:
- Die
keyMapper
ist eine Funktion, die einen Schlüssel, eine Art von „Kennung“ für die Einträge erstellt. In Ihrem Fall ist dies eine Funktion, die eine Foo
übernimmt und ein Objekt Entry<Integer, String>
erstellt, das als Schlüssel für die Karte verwendet wird. (Sie jede Pair
oder Tuple
es verwenden könnte - auch ein List<Object>
es tun würde)
- Die
valueMapper
kann die Identitätsfunktion
- Die
mergeFunction
ist wichtig hier: Es dauert zwei Foo
Objekte (mit der gleichen Anzahl und String) und gibt ein neues, verschmolzenes Objekt Foo
zurück, in dem die restlichen Werte hinzugefügt wurden.
Das Ergebnis wird ein Map
sein, aber Sie können einen List
aus den Werten dieser Karte erstellen, falls gewünscht.
Hier ein Beispiel:
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 + "]";
}
}
}
Ja, eine passiv-aggressive Bemerkung: Wenn Sie die Methodennamen usw. nicht mögen, dann sollten Sie uns Ihre aktuelle Foo
Klasse gezeigt haben. Wir haben, um ein bisschen hier zu raten ...
Bitte lesen Sie http://stackoverflow.com/help/how-to-ask. Es wird Ihnen helfen, Ihre Frage so zu formulieren, dass wir Ihnen helfen können. – jbrown
@jbrown Er möchte eine Methode, die eine 'ArrayList' von' Foo's akzeptiert und die gruppierte Version dieser 'ArrayList' zurückgibt. Beispiel: Iterieren Sie alle Elemente der Liste, überprüfen Sie, ob das Element bereits in der Liste vorhanden ist, die zurückgegeben wird, wenn es dann nicht hinzugefügt wird, wenn es die numerischen Werte zusammenführt. –
@nickzoum - nur die Idee von "Enthalten gerade genug Code, um anderen zu ermöglichen, das Problem zu reproduzieren" wie im verknüpften Dokument erläutert – jbrown