2

がありStream<String>、が欲しいですMap<Integer, String>。私の分類子関数を呼び出しましょうgetKey(String)- それは高価になる可能性があります。場合によってはゼロが返されます。これは、文字列を破棄し、結果のマップに含めないことを意味します。

したがって、次のコードを使用できます。

Stream<String> stringStream;
Map<Integer, String> result = 
    stringStream.collect(Collectors.groupingBy(this::getKey, Collectors.joining());
result.remove(0);

これにより、最初に不要な文字列がゼロでキー付けされたマップに追加され、次にそれらが削除されます。それらの多くがあるかもしれません。そもそもそれらをマップに追加しないようにするエレガントな方法はありますか?

グループ化の前にフィルター ステップを追加したくありません。これは、決定/分類コードを 2 回実行することを意味するためです。

4

2 に答える 2

3

呼び出しgetKeyはコストがかかるとおっしゃいましたが、ストリームの要素をフィルタリングする前に事前にマップすることはできます。この場合、への呼び出しgetKeyは 1 回だけ行われます。

Map<Integer, String> result =
    stringStream.map(s -> new SimpleEntry<>(this.getKey(s), s))
                .filter(e -> e.getKey() != 0)
                .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, joining()))); 

標準 API にはタプル クラスがないことに注意してください。自分で巻いてもいいAbstractMap.SimpleEntryし、代用してもいい。

または、最初のバージョンで多くのエントリが作成されると思われる場合は、collect メソッドを使用して、サプライヤ、アキュムレータ、コンバイナを自分で指定できます。

Map<Integer, String> result = stringStream
    .collect(HashMap::new, 
             (m, e) -> {
                 Integer key = this.getKey(e);
                 if(key != 0) {
                     m.merge(key, e, String::concat);
                 }
              }, 
              Map::putAll);
于 2016-01-12T16:20:48.460 に答える
2

次のようなペアのストリームを使用できます。

stringStream.map(x -> new Pair(getKey(x), x))
            .filter(pair -> pair.left != 0) // or whatever predicate
            .collect(Collectors.groupingBy(pair -> pair.left,
                        Collectors.mapping(pair -> pair.right, Collectors.joining())));

Pairこのコードは、 と の 2 つのフィールドleftを持つ単純なクラスを想定していますright

私のStreamExのような一部のサードパーティ ライブラリは、ボイラープレートを削除するための追加のメソッドを提供します。

StreamEx.of(stringStream)
        .mapToEntry(this::getKey, x -> x)
        .filterKeys(key -> key != 0) // or whatever
        .grouping(Collectors.joining());
于 2016-01-12T16:21:00.787 に答える