如何在使用 Stream API 的函数更改字符串变量的同时跟踪它?
How to keep track of a String variable while changing it with Functions using Stream API?
我想使用 Stream API 在使用函数更改变量时跟踪变量。
我的代码:
public String encoder(String texteClair) {
for (Crypteur crypteur : algo) {
texteClair = crypteur.encoder(texteClair);
}
return texteClair;
}
我有一个包含方法的 类 列表,我想在所有方法中放入一个变量,就像上面的代码所做的那样。
它工作得很好,但我想知道如何用流来完成它?
我们可以使用 reduce()
吗?
使用 AtomicReference
,它 最终有效 ,但它的包装值可能会改变:
public String encoder(String texteClair) {
AtomicReference<String> ref = new AtomicReference<>(texteClair);
algo.stream().forEach(c -> ref.updateAndGet(c::encoder)); // credit Ole V.V
return ref.get();
}
Could we use reduce()
?
我想我们可以。但请记住,使用流并不是最好的情况。
因为你提到了 "classes" 的复数形式,我假设 Crypteur
是一个 抽象 class 或 接口 。作为一般规则,您应该更喜欢 interfaces 而不是 abstract classes,所以我假设 Crypteur
是一个接口(如果不是,那不是什么大问题)并且它至少有一个类似于此的实现:
public interface Encoder {
String encoder(String str);
}
public class Crypteur implements Encoder {
private UnaryOperator<String> operator;
public Crypteur(UnaryOperator<String> operator) {
this.operator = operator;
}
@Override
public String encoder(String str) {
return operator.apply(str);
}
}
然后您可以像这样将编码器与流一起使用:
public static void main(String[] args) {
List<Crypteur> algo =
List.of(new Crypteur(str -> str.replaceAll("\p{Punct}|\p{Space}", "")),
new Crypteur(str -> str.toUpperCase(Locale.ROOT)),
new Crypteur(str -> str.replace('A', 'W')));
String result = encode(algo, "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system");
System.out.println(result);
}
public static String encode(Collection<Crypteur> algo, String str) {
return algo.stream()
.reduce(str,
(String result, Crypteur encoder) -> encoder.encoder(result),
(result1, result2) -> { throw new UnsupportedOperationException(); });
}
注意 combiner
,它在parallel中用于组合部分结果,故意抛出一个exception 表示此任务不可并行化。所有转换都必须按顺序应用,例如,我们不能在给定字符串上应用一些编码器,然后在给定字符串上单独应用其余编码器并合并两个结果 - 这是不可能的。
输出
EVERYPIECEOFKNOWLEDGEMUSTHWVEWSINGLEUNWMBIGUOUSWUTHORITWTIVEREPRESENTWTIONWITHINWSYSTEM
我想使用 Stream API 在使用函数更改变量时跟踪变量。
我的代码:
public String encoder(String texteClair) {
for (Crypteur crypteur : algo) {
texteClair = crypteur.encoder(texteClair);
}
return texteClair;
}
我有一个包含方法的 类 列表,我想在所有方法中放入一个变量,就像上面的代码所做的那样。
它工作得很好,但我想知道如何用流来完成它?
我们可以使用 reduce()
吗?
使用 AtomicReference
,它 最终有效 ,但它的包装值可能会改变:
public String encoder(String texteClair) {
AtomicReference<String> ref = new AtomicReference<>(texteClair);
algo.stream().forEach(c -> ref.updateAndGet(c::encoder)); // credit Ole V.V
return ref.get();
}
Could we use
reduce()
?
我想我们可以。但请记住,使用流并不是最好的情况。
因为你提到了 "classes" 的复数形式,我假设 Crypteur
是一个 抽象 class 或 接口 。作为一般规则,您应该更喜欢 interfaces 而不是 abstract classes,所以我假设 Crypteur
是一个接口(如果不是,那不是什么大问题)并且它至少有一个类似于此的实现:
public interface Encoder {
String encoder(String str);
}
public class Crypteur implements Encoder {
private UnaryOperator<String> operator;
public Crypteur(UnaryOperator<String> operator) {
this.operator = operator;
}
@Override
public String encoder(String str) {
return operator.apply(str);
}
}
然后您可以像这样将编码器与流一起使用:
public static void main(String[] args) {
List<Crypteur> algo =
List.of(new Crypteur(str -> str.replaceAll("\p{Punct}|\p{Space}", "")),
new Crypteur(str -> str.toUpperCase(Locale.ROOT)),
new Crypteur(str -> str.replace('A', 'W')));
String result = encode(algo, "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system");
System.out.println(result);
}
public static String encode(Collection<Crypteur> algo, String str) {
return algo.stream()
.reduce(str,
(String result, Crypteur encoder) -> encoder.encoder(result),
(result1, result2) -> { throw new UnsupportedOperationException(); });
}
注意 combiner
,它在parallel中用于组合部分结果,故意抛出一个exception 表示此任务不可并行化。所有转换都必须按顺序应用,例如,我们不能在给定字符串上应用一些编码器,然后在给定字符串上单独应用其余编码器并合并两个结果 - 这是不可能的。
输出
EVERYPIECEOFKNOWLEDGEMUSTHWVEWSINGLEUNWMBIGUOUSWUTHORITWTIVEREPRESENTWTIONWITHINWSYSTEM