Javaは、フィールドに収集カウントをストリーム

サミュエル・フィリップ:

可能な使用である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();

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=173581&siteId=1