用另一个流中的字符串替换一个流中的字符串
Replace string of one stream with string in another stream
流的乐趣...我有一个 List<String>
个标记化 URL,以及一个 List<UrlParametersConfig.UrlParameter>
个这些标记的所有参数值。例如,我的 yaml 文件如下所示:
urlParameterList:
urlParameter:
-
parameter: propertyId
value: c3329fc
-
parameter: cartId
value: 123456
...
相应的配置 class 如下所示:
@Configuration
@ConfigurationProperties(prefix="urlParameterList")
public class UrlParametersConfig {
private List<UrlParameter> urlParameters = new ArrayList<>();
public UrlParametersConfig() {}
public List<UrlParameter> getUrlParameter() { return this.urlParameters; }
public static class UrlParameter {
private String parameter;
private String value;
public String getParameter() {
return parameter;
}
public void setParameter(String parameter) {
this.parameter = parameter;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
所以我有一个 URL 列表,其中包含类似
www.comany.com/v2/rest/v2/property/{propertyId}
www.comany.com/v2/rest/v2/sale/{propertyId}/{cartId}
所有引用 {propertyId}
的地方我都需要替换 c3329fc
,而所有引用 {cartId}
的地方我都需要替换 123456a
。我发现我会使用两个流,但我不知道先流哪个,是所有 URL 的列表还是配置参数的列表。谁能告诉我这个令牌替换代码应该是什么样子?到目前为止,这就是我所拥有的:
List<String> parameterizeUrls = uris.stream()
.forEach(it -> {
if (it.contains(parameters.stream()
.map(UrlParametersConfig.UrlParameter::getParameter)
.collect(Collectors.toList()))
// do something?
});
如果我理解正确的话,我们希望获得以下信息:
www.comany.com/v2/rest/v2/property/c3329fc
www.comany.com/v2/rest/v2/sale/c3329fc/123456
需要一个流来在带有标记的原始 url
列表上循环。对于每个 url
,另一个流将在参数列表上循环,对每个参数执行 url
的缩减。
为了更清楚和避免过多嵌套,算法分为以下部分:
1) 主循环,将带有标记的原始 url 列表转换为带有替换值的 url:
List<String> urlsTokenReplaced = urls.stream().map(url ->
replaceTokens(url, params)
).collect(Collectors.toList());
2) 对于指定的 url
,替换列表中出现的每个标记。
private static String replaceTokens(String url, List<UrlParametersConfig.UrlParameter> params) {
return params.stream()
.reduce(url, {ClassName}::replaceToken, (prev, cur) -> cur);
}
更新
有关缩减操作工作原理的详细信息:Java tutorials。
对于这个特殊情况:
url
param为循环的起始值,例如www.comany.com/v2/rest/v2/sale/{propertyId}/{cartId}
.
{ClassName}::replaceToken
引用了下面的静态方法,就是so-calledaccumulator函数,取上一个(或起始)值并通过在其上应用当前 UrlParameter
来生成新值。在我们的例子中,在第一次传递时,它将在第二次传递时产生 www.comany.com/v2/rest/v2/sale/c3329fc/{cartId}
和 www.comany.com/v2/rest/v2/sale/c3329fc/123456
。
(prev, cur) -> cur)
是 so-called collector 函数。它定义了如何处理 prev
ious 和 cur
rent(由累加器产生)值。这里我们只是忘记了前一个值和 return 当前值,它们将在循环的下一次迭代中被累加器重用,依此类推。在我们的例子中,在第一次传递时它将 return www.comany.com/v2/rest/v2/sale/{propertyId}/{cartId}
和 www.comany.com/v2/rest/v2/sale/c3329fc/{cartId}
之间的第二个值。在第二遍中,它将 return 来自 www.comany.com/v2/rest/v2/sale/c3329fc/{cartId}
和 www.comany.com/v2/rest/v2/sale/c3329fc/123456
的第二个值。
当流中的所有 UrlParameter
都通过时,累加器(因此这里的收集器)产生的最后一个值是从方法中 returned 的。如果流为空,则起始值(第一个参数)将被 returned.
enf-of-update
3) 替换 url
:
中出现的指定标记
private static String replaceToken(String url, UrlParametersConfig.UrlParameter param) {
String replaceRegex = "\{" + param.getParameter() + "\}";
return url.replaceAll(replaceRegex, param.getValue());
}
流的乐趣...我有一个 List<String>
个标记化 URL,以及一个 List<UrlParametersConfig.UrlParameter>
个这些标记的所有参数值。例如,我的 yaml 文件如下所示:
urlParameterList:
urlParameter:
-
parameter: propertyId
value: c3329fc
-
parameter: cartId
value: 123456
...
相应的配置 class 如下所示:
@Configuration
@ConfigurationProperties(prefix="urlParameterList")
public class UrlParametersConfig {
private List<UrlParameter> urlParameters = new ArrayList<>();
public UrlParametersConfig() {}
public List<UrlParameter> getUrlParameter() { return this.urlParameters; }
public static class UrlParameter {
private String parameter;
private String value;
public String getParameter() {
return parameter;
}
public void setParameter(String parameter) {
this.parameter = parameter;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
所以我有一个 URL 列表,其中包含类似
www.comany.com/v2/rest/v2/property/{propertyId}
www.comany.com/v2/rest/v2/sale/{propertyId}/{cartId}
所有引用 {propertyId}
的地方我都需要替换 c3329fc
,而所有引用 {cartId}
的地方我都需要替换 123456a
。我发现我会使用两个流,但我不知道先流哪个,是所有 URL 的列表还是配置参数的列表。谁能告诉我这个令牌替换代码应该是什么样子?到目前为止,这就是我所拥有的:
List<String> parameterizeUrls = uris.stream()
.forEach(it -> {
if (it.contains(parameters.stream()
.map(UrlParametersConfig.UrlParameter::getParameter)
.collect(Collectors.toList()))
// do something?
});
如果我理解正确的话,我们希望获得以下信息:
www.comany.com/v2/rest/v2/property/c3329fc
www.comany.com/v2/rest/v2/sale/c3329fc/123456
需要一个流来在带有标记的原始 url
列表上循环。对于每个 url
,另一个流将在参数列表上循环,对每个参数执行 url
的缩减。
为了更清楚和避免过多嵌套,算法分为以下部分:
1) 主循环,将带有标记的原始 url 列表转换为带有替换值的 url:
List<String> urlsTokenReplaced = urls.stream().map(url ->
replaceTokens(url, params)
).collect(Collectors.toList());
2) 对于指定的 url
,替换列表中出现的每个标记。
private static String replaceTokens(String url, List<UrlParametersConfig.UrlParameter> params) {
return params.stream()
.reduce(url, {ClassName}::replaceToken, (prev, cur) -> cur);
}
更新
有关缩减操作工作原理的详细信息:Java tutorials。
对于这个特殊情况:
url
param为循环的起始值,例如www.comany.com/v2/rest/v2/sale/{propertyId}/{cartId}
.{ClassName}::replaceToken
引用了下面的静态方法,就是so-calledaccumulator函数,取上一个(或起始)值并通过在其上应用当前UrlParameter
来生成新值。在我们的例子中,在第一次传递时,它将在第二次传递时产生www.comany.com/v2/rest/v2/sale/c3329fc/{cartId}
和www.comany.com/v2/rest/v2/sale/c3329fc/123456
。(prev, cur) -> cur)
是 so-called collector 函数。它定义了如何处理prev
ious 和cur
rent(由累加器产生)值。这里我们只是忘记了前一个值和 return 当前值,它们将在循环的下一次迭代中被累加器重用,依此类推。在我们的例子中,在第一次传递时它将 returnwww.comany.com/v2/rest/v2/sale/{propertyId}/{cartId}
和www.comany.com/v2/rest/v2/sale/c3329fc/{cartId}
之间的第二个值。在第二遍中,它将 return 来自www.comany.com/v2/rest/v2/sale/c3329fc/{cartId}
和www.comany.com/v2/rest/v2/sale/c3329fc/123456
的第二个值。
当流中的所有 UrlParameter
都通过时,累加器(因此这里的收集器)产生的最后一个值是从方法中 returned 的。如果流为空,则起始值(第一个参数)将被 returned.
enf-of-update
3) 替换 url
:
private static String replaceToken(String url, UrlParametersConfig.UrlParameter param) {
String replaceRegex = "\{" + param.getParameter() + "\}";
return url.replaceAll(replaceRegex, param.getValue());
}