gpt4 book ai didi

java - 在 Java 中使用不纯函数迭代 Collection 的最佳实践

转载 作者:行者123 更新时间:2023-12-05 04:21:24 26 4
gpt4 key购买 nike

假设这是用例:我想更新类(class)内的 Hashmap 缓存。我有一组键和一些条件,我想将这些条件应用于键和使用键检索的值。


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

public class App {

Set<String> keysToUpdate;
HashMap<String, List<String>> cache;

void buildCache(){
keysToUpdate.stream()
.filter(k -> true) // some filter
.forEach(
key ->{
// now values list comes from outside the stream pipeline
List<String> values = cache.computeIfAbsent(key, k -> new ArrayList<>());
getValuesforKey(key)
.stream()
.filter(k -> true) //another filter
// side effects are introduced
.forEach(value -> {
//some other operation, for example logging the values added like
// log.info("{} value added", value);
values.add(value);
}
);
}

);
}
private List<String> getValuesforKey(String key) {
//some method to get the values for the key
return new ArrayList<>();
}
}

我们被告知这样的共享可变性很糟糕,因为执行不是确定性的,但在这种特定情况下,我将值添加到 hashmap 并且我不关心执行顺序,如果我知道 keysToUpdate 不包含重复值。

是否还有其他方面我没有考虑到?如果流是并行化的,此代码是否安全?

如果不是,使用集合的迭代器是否可以解决问题? (下面的代码)。还是最好改用命令式编程?在什么情况下流中共享可变性 OK

public class App {

Set<String> keysToUpdate;
HashMap<String, List<String>> cache;

void buildCache(){
keysToUpdate.stream()
.filter(k -> true)// some filter
.collect(Collectors.toList()) // Collect before iterating
.forEach(
key ->{
// now values list comes from outside the stream pipeline
List<String> values = cache.computeIfAbsent(key, k -> new ArrayList<>());
getValuesforKey(key)
.stream()
.filter(k -> true) 、、another filter
.collect(Collectors.toList()) // Collect before iterating
// side effects are introduced
.forEach(value -> {
//some other operation, for example logging the values added like
// log.info("{} value added", value);
values.add(value);
}
);
}

);
}
private List<String> getValuesforKey(String key) {
//some method to get the values for the key
return new ArrayList<>();
}
}

最佳答案

在处理多线程时,要回答的问题是是否会发生竞争条件(即,如果两个或多个不同的线程可能同时访问同一资源,并且至少有一个线程试图修改它)。

在您的示例中,如果请求的键不存在,computeIfAbsent 方法将修改您的 map 。因此,两个线程可能会修改同一资源(cache 对象)。为避免这种情况,您可以(在 buildCache 方法的开头)使用 Collections.synchronizedMap() 获取 map 的线程安全版本,然后对返回 map 。

对于 values 列表,安全取决于两个线程是否可以操作同一个键,从而修改同一个列表。在您的示例中, key 是唯一的,因为是从集合中获取的,因此代码是安全的。

旁注:预期的性能提升取决于 getValuesForKey 方法必须执行的处理量。如果忽略不计,大多数线程将只是等待 map 上的锁,从而使性能提升也微乎其微。

关于java - 在 Java 中使用不纯函数迭代 Collection 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74217917/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com