サミュエル・フィリップ:
可能な使用であるCollectors.groupingBy()
とのCollectors.counting()
代わりにマップを作成し、その後、それを変換するカスタムオブジェクトのフィールドにカウントします。
私はこのように、ユーザのリストを持っています:
public class User {
private String firstName;
private String lastName;
// some more attributes
// getters and setters
}
私は同じ姓と名を持つすべてのユーザーをカウントします。したがって、私は、カスタムオブジェクトのように見ています
public static class NameGroup {
private String firstName;
private String lastName;
private long count;
// getters and setters
}
私はこれを使用して名前のグループを収集することができます。
List<NameGroup> names = users.stream()
.collect(Collectors.groupingBy(p -> Arrays.asList(p.getFirstName(), p.getLastName()), Collectors.counting()))
.entrySet().stream()
.map(e -> new NameGroup(e.getKey().get(0), e.getKey().get(1), e.getValue()))
.collect(Collectors.toList());
このソリューションでは、私はグループに最初のマップにユーザーを持っていると私のカスタムオブジェクトに、後でそれを変換します。それが直接、すべての名前をカウントすることが可能であるnameGroup.count
リスト(またはマップ)の上に二回反復を回避し、パフォーマンスを向上させますか?
アンドレアス:
あなたはすべて例えば、中間オブジェクトの割り当てを最小限に抑えることができますArrays.asList(...)
代わりにストリーミング使用するのでは、ビルドにより、オブジェクトマップを自分で。
これは、あなたがいるという事実に依存してNameGroup
変更可能です。
でも、コードを簡単にするために、2つのヘルパーをして追加することができますNameGroup
:
public static class NameGroup {
// fields here
public NameGroup(User user) {
this.firstName = user.getFirstName();
this.lastName = user.getLastName();
}
public void incrementCount() {
this.count++;
}
// other constructors, getters and setters here
}
代わりにそれを使用すると、このようなロジックを実装することができます:
Map<User, NameGroup> map = new TreeMap<>(Comparator.comparing(User::getFirstName)
.thenComparing(User::getLastName));
users.stream().forEach(user -> map.computeIfAbsent(user, NameGroup::new).incrementCount());
List<NameGroup> names = new ArrayList<>(map.values());
あなたが実際にリストを必要としない場合は、最後の行はように簡略化することができます。
Collection<NameGroup> names = map.values();