Scalaの素晴らしいfoldLeft
in Java 8と同等のものは何ですか?
私はそれがreduce
であると考えたがりましたが、reduceはそれが還元するものと同じ型の何かを返さなければなりません。
例:
_import Java.util.List;
public class Foo {
// this method works pretty well
public int sum(List<Integer> numbers) {
return numbers.stream()
.reduce(0, (acc, n) -> (acc + n));
}
// this method makes the file not compile
public String concatenate(List<Character> chars) {
return chars.stream()
.reduce(new StringBuilder(""), (acc, c) -> acc.append(c)).toString();
}
}
_
上記のコードの問題はacc
umulatorです:new StringBuilder("")
したがって、誰かが私にfoldLeft
/の適切な同等物を指し示すことができますか?私のコードを修正しますか?
更新:
コードを修正する最初の試みは次のとおりです。
public static String concatenate(List<Character> chars) {
return chars
.stream()
.reduce(new StringBuilder(),
StringBuilder::append,
StringBuilder::append).toString();
}
次の reduceメソッド を使用します。
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
紛らわしいかもしれませんが、javadocsを見ると、詳細をすばやく把握するのに役立つ説明があります。この削減は、次のコードと同等です。
U result = identity;
for (T element : this stream)
result = accumulator.apply(result, element)
return result;
より詳細な説明については、 this source を確認してください。
ただし、アキュムレータがであるべきであるreduceの規約に違反しているため、この使用法は正しくありません(= /// =)、結果に追加要素を組み込むための連想、非干渉、ステートレス関数です。言い換えると、IDは変更可能であるため、並列実行の場合、結果は壊れます。
以下のコメントで指摘されているように、正しいオプションは次のように削減を使用しています。
return chars.stream().collect(
StringBuilder::new,
StringBuilder::append,
StringBuilder::append).toString();
サプライヤーStringBuilder::new
は、後で結合される再利用可能なコンテナを作成するために使用されます。
Java 8のストリームAPIにfoldLeft
に相当するものはありません。他の人が述べたように、reduce(identity, accumulator, combiner)
は近くにありますが、foldLeft
結果の型B
がそれ自体と結合し、すべての型が持つわけではないプロパティである連想的(言い換えれば、モノイドのようなもの)である必要があります。
このための機能強化リクエストもあります: add Stream.foldLeft()terminal operation
Reduceが機能しない理由を確認するには、次のコードを検討します。ここでは、指定された数値で始まる一連の算術演算を実行します。
_val arithOps = List(('+', 1), ('*', 4), ('-', 2), ('/', 5))
val fun: (Int, (Char, Int)) => Int = {
case (x, ('+', y)) => x + y
case (x, ('-', y)) => x - y
case (x, ('*', y)) => x * y
case (x, ('/', y)) => x / y
}
val number = 2
arithOps.foldLeft(number)(fun) // ((2 + 1) * 4 - 2) / 5
_
reduce(2, fun, combine)
を記述しようとした場合、2つの数値を結合するどの結合関数を渡すことができますか? 2つの数字を一緒に追加しても明らかに解決しません。また、値_2
_は明らかにidentity要素ではありません。
順次実行を必要とする操作は、reduce
で表現できないことに注意してください。 foldLeft
は実際にはreduce
よりも汎用的です。reduce
でfoldLeft
を実装できますが、foldLeft
でreduce
を実装することはできません。
探しているメソッドは Java.util.Stream.reduce
、特に、3つのパラメーター、identity、accumulator、およびbinary functionを含むオーバーロード。これは、ScalaのfoldLeft
と同等の正しいものです。
ただし、Javaのreduce
をそのまま使用することはnot許可されており、ScalaのfoldLeft
も使用できません。代わりに collect
を使用してください。
他のものは正しいが、同等のものはない。こちらがユーティリティです。
<U, T> U foldLeft(Collection<T> sequence, U identity, BiFunction<U, ? super T, U> accumulator) {
U result = identity;
for (T element : sequence)
result = accumulator.apply(result, element);
return result;
}
上記の方法を使用した場合は次のようになります-
public String concatenate(List<Character> chars) {
return foldLeft(chars, new StringBuilder(""), StringBuilder::append).toString();
}
または、ラムダメソッドref sugarなしで、
public String concatenate(List<Character> chars) {
return foldLeft(chars, new StringBuilder(""), (stringBuilder, character) -> stringBuilder.append(character)).toString();
}