本篇是记录自己在学习中遇到一些用法(比较泛,只要是我认为比较奇怪,惊艳的,有价值的都可以)。还有一些我经常会用到的和一些有趣的封装,先记录吧,可能后面多了会很乱,到时再说。
null字符串
这是一个很有意思的现象,我到现在才知道,原来会出现
String name = null;
System.out.println(name+"");
System.out.println(""+null); //"null"
System.out.println(String.valueOf(name)); //"null"
"null"这样的字符串。无论是""+null还是String.valueOf(name),Object name=null都会形成“null”字符串,而""+null的写法比较简洁,不会太长,所以一般我喜欢用前面一种(个人喜好)。
这里说这个现象的目的是:在判断字符串的时候,不要只考虑两种情况,还有第三种:
- 字符串为null
- 字符串为空字符串
- 字符串为"null"(null字符串)
String name = String.valueOf(...从request中获得请求参数)+""
if(name!=null && !"".equals(name) && "null".equals(name)){
...
}
32位的md5加密,全部小写(大写)
这个加密代码我是从网上查的,版本感觉都差不多,不过还有另外一种比较简洁的版本,下面会有说到。
/**
*签名32位md5加密,全小写
*
*/
public static String getSign(String account, String pwd, String timestamp)
throws NoSuchAlgorithmException{
String sign = account+pwd+timestamp;
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(sign.getBytes("UTF-8"));
byte b[] = md5.digest();
int i;
StringBuffer sf = new StringBuffer("");
for(int offset=0; offset<b.length; offset++){
i = b[offset];
if(i<0){
i=i+256;
}
if(i<16){
sf.append("0");
}
sf.append(Integer.toHexString(i));
return sf.toString().toLowerCase();
}
}
使用给定的密钥进行MD5加密,32位,大写,字符串用GBK编码。
/**
* 用给定的密钥对字符串进行32位的md5加密,全大写,字符集采用GBK
* @param str 待加密字符串
* @param key 密钥
* @return
*/
public static String getSign(String str, String key){
StringBuffer sf = new StringBuffer("");
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(str.getBytes("GBK"));
yte temp[] = md5.digest(key.getBytes("UTF-8"));
for(int i=0; i<temp.length; i++){
sf.append(Integer.toHexString((temp[i] & 0x000000FF) |
0xFFFFFF00).substring(6));
}
return sf.toString().toUpperCase();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return sf.toString().toUpperCase();
}
随机数
生成n位随机数
这是别人写的标题是链接,简单说一下原理,一开始现将,[0,1)*9+1=[1,10),然后根据需要将[1,10)*10^(n-1)。
/**
* 生成n位随机数
* @param n 随机数的长度
* @return
*/
public static long getNDigitRanNum(int n){
if(n < 1){
throw new IllegalArgumentException("随机数位数必须大于0");
}
return (long)(Math.random()*9*Math.pow(10,n-1)) + (long)Math.pow(10,n-1);
}
自定义范围的随机数
/**
* 生成指定上下界的随机数
* [0, maxBound)%range=[0, range)+minBound=[minBound, minBound+range)
* @param minBound 下界
* @param maxBound 上界
* @return
*/
public static int getRandomNumInRange(int minBound, int maxBound){
Random random = new Random();
return random.nextInt(maxBound)%(maxBound-minBound+1)+minBound;
}
随机事件(指定事件发生概率)
大致的需求是:比如说,有三种情况,第一种情况的出现概率为2/5;第二种情况的出现概率为2/5;最后一种出现的概率为1/5。实现的原理比较简单,复用上面的方法,然后对随机的区域进行分割,判定最后随机数落在哪个范围内,返回所需对应的字符串,具体看代码注释,代码有点乱。之所以写这个主要是有次写测试的时候,请求接口会返回三种状态,所以写了一个,感觉比较有趣就记下来了。。
/**
* events:key(事件):value(概率),用TreeMap保持加入的顺序
* 0.4,0.4,0.2
* 400,800,1000
* @param events 随机事件
* @return
*/
public static String probabilityEvent(TreeMap<String, Double> events){
double p_total = 1.0;
int random = getRandomNumInRange(0, 1000); //取出随机范围为0~999的一个随机数
int index = 0;
String result = "";
for(Map.Entry<String, Double> event : events.entrySet()){
p_total = p_total - event.getValue(); //用于检查事件总概率小于1
if("".equals(event.getKey().trim()) || event.getValue()<=0.0 || event.getValue()>=1.0){
throw new IllegalArgumentException("事件不得为空,事件概率不能小于0大于1");
}
int range = (int)(event.getValue()*1000); //计算出该概率在1000中所占的范围
index = index + range;
//用""来控制不重复获取事件
if("".equals(result) && random<index){
result = event.getKey();
}
}
if(p_total<0.0){
throw new IllegalArgumentException("事件概率相加必须小于1");
}
return result;
}