太懒不准备再写demo,直接项目上的代码。。。
public String getSvcsWithNamespaceAndDeployment(ProxyAuth auth, String clusterId, String namespace,String deployment) {
log.info("获取集群ID:{},命名空间:{},deploy:{},对应svc",clusterId,namespace,deployment);
List<io.fabric8.kubernetes.api.model.Service> services = kubernetesAPI.getServicesNew(auth, clusterId, namespace, null);
Deployment deploy = kubernetesAPI.getDeployment(auth, clusterId, namespace, deployment);
List<io.fabric8.kubernetes.api.model.Service> svc = Lists.newArrayList();
services.forEach(service -> {
AtomicBoolean match = new AtomicBoolean(true);
Map<String,String> maps = service.getSpec().getSelector();
Map<String,String> des = deploy.getSpec().getSelector().getMatchLabels();
des.forEach((k,v) -> {
if(null != maps) {
String value = maps.get(k);
if(value == null || !value.equals(v)) {
match.set(false);
return;
}
}else{
match.set(false);
return;
}
});
if(match.get()) {
svc.add(service);
}
});
ObjectMapper mapper = new ObjectMapper();
try {
String json = mapper.writeValueAsString(svc);
return json;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
log.info("获取svc:{}",svc);
return null;
}
之前某位码哥写的代码,其实业务还是挺简单的,但是由于要避免迭代list的时候删除元素出问题,他的做法是新创建了一个集合,然后又搞了一个标志位,当标志位为true的时候把数据放入新的集合中,说实话挺麻烦,而且代码可读性差。
所以对代码进行了第一次优化,首先想到的是CopyOnWriteArrayList这个类,这是一个线程安全的集合类采用的是读写分离,在迭代的时候是可以删除元素的,好处是省略了标志位并且可读性稍高,代码如下
public List<io.fabric8.kubernetes.api.model.Service> getSvcsWithNamespaceAndDeployment(ProxyAuth auth, String clusterId, String namespace,String deployment) {
log.info("获取集群ID:{},命名空间:{},deploy:{},对应svc",clusterId,namespace,deployment);
List<io.fabric8.kubernetes.api.model.Service> services = kubernetesAPI.getServicesNew(auth, clusterId, namespace, null);
CopyOnWriteArrayList<io.fabric8.kubernetes.api.model.Service> svcs = new CopyOnWriteArrayList(services.toArray());
Deployment deploy = kubernetesAPI.getDeployment(auth,clusterId,namespace,deployment);
svcs.forEach(service -> {
Map<String,String> maps = service.getSpec().getSelector();
if(null != maps) {
deploy.getSpec().getSelector().getMatchLabels().forEach((k,v) -> {
String value = maps.get(k);
if(value == null || !value.equals(v)) {
svcs.remove(service);
return;
}
});
}else{
svcs.remove(service);
return;
}
});
log.info("获取deployment对应的svc:{}",svcs);
return svcs;
}
想到都用stream流编程了,使用filter进行过滤下吧,代码如下
public List<io.fabric8.kubernetes.api.model.Service> getSvcsWithNamespaceAndDeployment(ProxyAuth auth, String clusterId, String namespace,String deployment) {
log.info("获取集群ID:{},命名空间:{},deploy:{},对应svc",clusterId,namespace,deployment);
List<io.fabric8.kubernetes.api.model.Service> services = kubernetesAPI.getServicesNew(auth, clusterId, namespace, null);
Deployment deploy = kubernetesAPI.getDeployment(auth,clusterId,namespace,deployment);
List<io.fabric8.kubernetes.api.model.Service> svcs = services.stream()
.filter(service -> null != service.getSpec().getSelector())
.filter(service -> deploy.getSpec().getSelector().getMatchLabels()
.entrySet().stream().anyMatch(entry -> {
String value = service.getSpec().getSelector().get(entry.getKey());
return null != value && value.equals(entry.getValue());
})
)
.collect(Collectors.toList());
log.info("获取deployment对应的svc:{}",svcs);
return svcs;
}
原来的foreach使用的是外部迭代,stream中的迭代是内部迭代没有迭代器iterator,如果数据量比较大处理比较繁琐的时候内部迭代效率会比较高。stream中也有foreach,它是一个终端操作,在里面进行不了元素更改的操作,所以只能用filter(中端操作)进行过滤。明显发现使用stream编程代码可读性比之前高不少。