2015-05-26 6 views
7

Ich möchte die verschiedenen Elemente eines Stroms zählen und frage mich, warumCounting Elemente eines Stream-

Stream<String> stream = Stream.of("a", "b", "a", "c", "c", "a", "a", "d"); 
Map<String, Integer> counter1 = stream.collect(Collectors.toMap(s -> s, 1, Integer::sum)); 

funktioniert nicht. Eclipse sagt mir

Verfahren toMap (Funktion, Funktion, BinaryOperator) in der Art Collectors ist nicht anwendbar für die Argumente ((n) -> {}, int, Integer :: sum)

By the way, weiß ich über diese Lösung:

Map<String, Long> counter2 = stream.collect(Collectors.groupingBy(s -> s, Collectors.counting())); 

So habe ich zwei Fragen:

  1. Was th Ein Fehler in meinem ersten Ansatz?
  2. Wie würden Sie einen solchen Zähler implementieren?

EDIT: löste ich die erste Frage von mir:

Map<String, Integer> counter1 = stream.collect(Collectors.toMap(s -> s, s -> 1, Integer::sum)); 

Java ist eine Funktion als zweites Argument erwartet.

+2

Wenn Sie die Frage selbst gelöst haben, schreiben Sie einfach eine Antwort, anstatt die Frage zu bearbeiten. –

+0

@TagirValeev Es ist nur der erste Teil. Soll eine Antwort nicht die ganze Frage beantworten? Ich möchte auch, dass die Leute nicht länger darüber besorgt sind, mir zu sagen, was ich falsch gemacht habe. –

+0

http://stackoverflow.com/questions/25441088/group-by-counting-in-java8-stream-api –

Antwort

4

Es gibt tatsächlich mehrere Möglichkeiten, dies zu tun. Die eine, die Sie nicht erwähnt haben, ist .collect(groupingBy(x -> x, summingInt(x -> 1)));

Es gibt einige Unterschiede in der Leistung.

Approach # 1 wird am besten sein, wenn es nur sehr wenige Objekte pro Bucket gibt. Im Idealfall von nur einem Objekt pro Bucket erhalten Sie sofort die endgültige Map, ohne dass die Einträge geändert werden müssen. Im schlimmsten Fall einer sehr großen Anzahl von wiederholten Objekten, wird es viel Boxen/Unboxing zu tun haben.

Approach # 2 beruht auf counting() Kollektor, der nicht genau angibt, wie es das Zählen tun sollte. Die aktuelle Implementierung wird an reducing weitergeleitet, aber das könnte sich ändern.

Der Ansatz summingInt akkumuliert die Zählung in int statt Integer und wird daher keine Boxing/Unboxing erfordern. Es wird am besten sein, wenn sich Objekte sehr oft wiederholen.

Für welche zu wählen, ist es am besten, für Klarheit zu kodieren und zu optimieren, wenn es notwendig wird. Für mich drückt groupingBy(x->x, counting()) die Absicht am deutlichsten aus, das ist also diejenige, die ich bevorzugen würde.