前言
本文主要记录最近工作中关于开发中的一些小技巧以及感悟
小细节
权重转换百分比的问题
在工作中需要将各个对象所对应的权重转换成百分比,并且要求最后转换出来的百分比,同一类型的相加必须为百分之百,解决思路主要如下
- 将各个类型的对象都分别分类
- 算出各个类型的总权重
- 算出每个对象在自己类型下的所占百分比
- 判断每个类型下的对象百分比相加是否等于100
- 在List处理的时候,可以将List分割成当前类型,和非当前类型 其中需要注意的是,在算百分比的时候,*100应该写在分子
eg: //这样会一直为0,是错误的 //原因是运算符是从左往右计算 //前面除法算出来之后会直接去尾,不足1就是0,所以最后乘以100结果还是0 percent / totalWeight * 100 //这样是正确的 percent * 100 / totalWeight
code:
private List<GreyDestination> getDestinationsPercent(List<GreyDestination> tempDestinations) {
HashMap<String, Integer> serviceAndTotalWeight = new HashMap<>();
HashMap<String, Integer> serviceAndCount = new HashMap<>();
getServiceWeightAndCount(tempDestinations, serviceAndTotalWeight, serviceAndCount);
List<GreyDestination> finalDestinations = tempDestinations.stream().map(
destination -> {
String service = destination.getService();
Integer count = serviceAndCount.get(service);
if (count == 1) {
destination.setPercent(100);
} else {
Integer totalWeight = serviceAndTotalWeight.get(service);
if (totalWeight == 0) {
totalWeight = 1;
}
destination.setPercent(destination.getWeight() * 100 / serviceAndTotalWeight.get(service));
}
return destination;
}
).collect(Collectors.toList());
for (String service : serviceAndCount.keySet()) {
if (serviceAndCount.get(service) > 1) {
List<GreyDestination> collectService = finalDestinations.stream().filter(destination -> destination.getService().equals(service)).collect(Collectors.toList());
List<GreyDestination> collectRest = finalDestinations.stream().filter(destination -> !destination.getService().equals(service)).collect(Collectors.toList());
Integer firstPercet= 100;
for (int i = 1; i < collectService.size(); i++) {
firstPercet = firstPercet-collectService.get(i).getPercent();
}
GreyDestination firstDestination = collectService.get(0);
firstDestination.setPercent(firstPercet);
collectService.set(0, firstDestination);
collectService.addAll(collectRest);
finalDestinations=collectService;
}
}
return finalDestinations;
}
private void getServiceWeightAndCount(List<GreyDestination> tempDestinations, HashMap<String, Integer> serviceAndTotalWeight, HashMap<String, Integer> serviceAndCount) {
for (GreyDestination tempDestination : tempDestinations) {
String service = tempDestination.getService();
Integer weight = tempDestination.getWeight();
//存储每个service的count
if (serviceAndCount.containsKey(service)) {
serviceAndCount.put(service, serviceAndCount.get(service) + 1);
} else {
serviceAndCount.put(service, 1);
}
//增加每个Service的total weight
if (serviceAndTotalWeight.containsKey(service)) {
serviceAndTotalWeight.put(service, serviceAndTotalWeight.get(service) + weight);
} else {
serviceAndTotalWeight.put(service, weight);
}
}
}
公共基础父类
例如 分页模块,应该在父类定制一个最简单的模型,然后在各个业务Service中继承的时候,分别定制化各个服务中特有的特征,已达到方法真正的可扩展性和可复用性。
单例模式
这个常见的设计模式,主要是用来保证这个对象,只会被实例化一次,比如在线程池中的时候
泛型
三种类型
-
泛型接口(写在接口名之后)
public interface List<E> extends Collection<E>
-
泛型类(将泛型写在类名之后)
class Test<T>{ private T data; }
-
泛型方法(将泛型写在方法返回值之前)
public static <T extends Comparable> void sort(T[] arr, int left, int right)
实例code
package QuickSort;
import com.google.common.base.Joiner;
/**
* Created by ymk on 2019/3/29.
* 这个类主要是用来实现快速排序的
*/
public class QuickSort {
public static <T extends Comparable> void sort(T[] arr, int left, int right) {
if (left >= right)
return;
int i = left, j = right;
T key = arr[i];
while (i < j) {
while (arr[j].compareTo(key) >= 0 && i < j) {
j--;
}
//j找到第一个比key小的值,i和j交换值
swap(arr,i,j);
while (arr[i].compareTo(key) <= 0 && i < j) {
i++;
}
//i找到第一个比key大的值,i和j交换值
swap(arr,i,j);
}
//开始递归
sort(arr,left,i);
sort(arr,i+1,right);
}
public static <T> void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
Integer[] arr={1,2,325,52,34,5346,23,23,56,74,34,634,74,34};
Joiner joiner = Joiner.on(",");
System.out.println(joiner.join(arr));
sort(arr,0,arr.length-1);
System.out.println(joiner.join(arr));
}
}
分布式锁的问题
最近工作中的后台服务,部署在了测试环境中的两个节点上,然后执行同一个定时任务的时候,虽然都写了在更新之前先删除库中信息,然后再将新的数据入库的操作,但是实际部署之后,还是会出现数据的冗余,原因应该是在某一瞬间,两个服务同时删除了库,然后同时插入了相同的数据。虽然过一段时间后就数据再次就正常了,但是这还是一个问题
可以使用分布式锁,将锁放在redis当中(分布式问题之所以复杂,就是因为网络延迟和网络不可靠的问题)setnx ,get等等(有可能会出现阻塞的情况,比如在操作的时候宕机了,来不及释放),具体有机会的时候,实践一下吧
顺便复习一下死锁的四个必要条件:
- 排他性
- 请求和保持资源
- 不剥夺资源
- 形成等待环路