我正在学习Java 8,我想用java Stream重写常用的java代码。好让它做得更好。我的代码:
public Set<Product> getProductsByFilter(Map<String, List<String>>filterParams) {
Set<Product> productsByBrand = new HashSet<Product>();
Set<Product> productsByCategory = new HashSet<Product>();
Set<String> criterias = filterParams.keySet();
if (criterias.contains("brand")) {
for (String brandName : filterParams.get("brand")) {
for (Product product : listOfProducts) {
if (brandName.equalsIgnoreCase(product.
getManufacturer())) {
productsByBrand.add(product);
}
}
}
}
if (criterias.contains("category")) {
for (String category : filterParams.get("category")) {
productsByCategory.addAll(this.
getProductsByCategory(category));
}
}
productsByCategory.retainAll(productsByBrand);
return productsByCategory;
}
我不知道如何校正if (criterias.contains("brand"))中的重新格式化代码。
发布于 2018-06-02 06:35:47
如果代码可以工作,为什么要更改它呢?然而,这里有一个使用流API的解决方案:
public Set<Product> getProductsByFilter(Map<String, List<String>> filterParams) {
Set<Product> productsByBrand = filterParams.containsKey("brand") ?
filterParams.get("brand")
.stream()
.flatMap(brandName -> listOfProducts.stream()
.filter(product -> brandName.equalsIgnoreCase(product.getManufacturer())))
.collect(Collectors.toCollection(HashSet::new)) : new HashSet<>();
Set<Product> productsByCategory =
filterParams.containsKey("category") ?
filterParams.get("category")
.stream()
.flatMap(category -> this.getProductsByCategory(category).stream())
.collect(Collectors.toCollection(HashSet::new)) : new HashSet<>();
productsByCategory.retainAll(productsByBrand);
return productsByCategory;
}
或者正如@shmosel所建议的那样,您可以使用getOrDefault来避免使用三元运算符
Set<Product> productsByBrand =
filterParams.getOrDefault("brand", Collections.emptyList())
.stream()
.flatMap(brandName -> listOfProducts.stream()
.filter(product -> brandName.equalsIgnoreCase(product.getManufacturer())))
.collect(Collectors.toCollection(HashSet::new));
Set<Product> productsByCategory =
filterParams.getOrDefault("category", Collections.emptyList())
.stream()
.flatMap(category -> this.getProductsByCategory(category).stream())
.collect(Collectors.toCollection(HashSet::new));
发布于 2018-06-02 07:28:27
这里试图让它尽可能地基于lambda-stream。
首先,如果忽略任何一个条件(品牌或类别),则当前问题代码将返回一个空集。如果这不是bug,而是预期的行为,那么检查是否是这种情况并快速返回空集是很有意义的。因此,代码可以像这样开始:
final List<String> filterBrands = filterParams.getOrDefault("brand", Collections.emptyList()));
final List<String> filterCategories = filterParams.getOrDefault("categories", Collections.emptyList()));
if (filterCategories.isEmpty() || filterCategories.isEmpty()) {
return Collections.emptySet();
}
如果第一个列表是空的,您可以避免组成第二个列表,但它添加了几行代码,并且增益很可能是超级可以忽略的。
对于这一点,您可以使用另一种答案方法,即创建两个标准产品集,然后使用交集。然而,由于您可以直接从产品访问品牌,也就是制造商,因此有一种替代方案不需要明确地实例化这样的集合,因此我们可能会提高性能,这取决于返回大小与每个标准集合的比率。所以如果结果只是几个产品...比方说5,但每个标准或其中一个标准集可能最终只有1000秒,这样做可以节省内存或cpu:
final Set<String> manufacturers = filterBrands.stream()
.map(String::toLowerCase)
.collect(Collectors.toSet());
return filterCategories.stream()
.flatMap(this::getProductsByCategory)
.distinct() // optional but might be better performance
// if categories share products.
.filter(product -> manufacturers.contains(product.getManufacturer().toLowerCase()))
.collect(Collectors.toSet());
https://stackoverflow.com/questions/50651580
复制相似问题