我正在尝试使用流将一个列表映射到另一个列表。
原始列表的某些元素无法映射。也就是说,映射函数可能无法找到适当的新值。
我想知道是否有任何映射失败。理想情况下,我还想在发生故障时停止处理。
我目前正在做的是:
myApp.filter('addNumToEachLetter', function(){
return function(str){
return str.split('').map(function(c, index){ return c + (index+1)}).join('');
}
})
myApp.controller('mainController', ['$scope', '$filter', function($scope, $filter){
$scope.someString = '';
$scope.uppercase = function(){
return $filter('uppercase')($scope.someString);
},
$scope.lowercase = function(){
return $filter('lowercase')($scope.someString);
},
$scope.addNumToEachLetter = function(){
return $filter('addNumToEachLetter')($scope.someString);
}
}]);
null
从流中删除空值filter()
,然后例如:
collect()
这不是很优雅。而且,即使整个事情都失败,一切都会得到处理。
建议更好的方法吗? 或者也许我应该完全抛弃流并使用旧的循环?
答案 0 :(得分:1)
没有最佳解决方案,因为这在很大程度上取决于用例。例如。如果预期查找失败不可能或者错误处理意味着抛出异常,那么在映射函数中的第一次失败查找中抛出异常可能确实是一个不错的选择。然后,没有后续代码必须关心错误条件。
另一种处理方法可能是:
List<String> func(List<String> old, Map<String, String> oldToNew) {
Map<Boolean,List<String>> map=old.stream()
.map(oldToNew::get)
.collect(Collectors.partitioningBy(Objects::nonNull));
List<String> failed=map.get(false);
if(!failed.isEmpty())
throw new IllegalStateException(failed.size()+" lookups failed");
return map.get(true);
}
这仍然可以被认为是针对成功案例进行了优化,因为它收集了一个包含失败的null
值的无意义的列表。但它能够分辨失败次数(与使用投掷地图功能不同)。
如果详细的错误分析具有高优先级,您可以使用如下解决方案:
List<String> func(List<String> old, Map<String, String> oldToNew) {
Map<Boolean,List<String>> map=old.stream()
.map(s -> new AbstractMap.SimpleImmutableEntry<>(s, oldToNew.get(s)))
.collect(Collectors.partitioningBy(e -> e.getValue()!=null,
Collectors.mapping(e -> Optional.ofNullable(e.getValue()).orElse(e.getKey()),
Collectors.toList())));
List<String> failed=map.get(false);
if(!failed.isEmpty())
throw new IllegalStateException("The following key(s) failed: "+failed);
return map.get(true);
}
它收集两个有意义的列表,包含失败的查找失败的键和成功映射的值列表。请注意,可以返回两个列表。
答案 1 :(得分:0)
您可以将过滤器更改为Objects::requireNonNull
并在流外捕获NullPointerException