十九、Java中对Map(HashMap,TreeMap,Hashtable等)的排序
首先简单说一下他们之间的区别:
HashMap: 最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为 Null。非同步的。
TreeMap: 能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。
Hashtable: 与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。
LinkedHashMap: 保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。
TreeMap默认按key进行升序排序,如果想改变默认的顺序,可以使用比较器:
Map<String,String> map = new TreeMap<String,String>(new Comparator<String>(){
public int compare(String obj1,String obj2){
//降序排序
return obj2.compareTo(obj1);
}
});
map.put("month", "The month");
map.put("bread", "The bread");
map.put("attack", "The attack");
Set<String> keySet = map.keySet();
Iterator<String> iter = keySet.iterator();
while(iter.hasNext()){
String key = iter.next();
System.out.println(key+":"+map.get(key));
}
如果要对 TreeMap 按照 value 的值进行排序,或者对 HashMap,Hashtable,LinkedHashMap 进行排序,则可以使用 Map.Entry<K,V> 接口结合List实现:
eg.1 对TreeMap按照value值升序:
List<Map.Entry<String,String>> mappingList = null;
Map<String,String> map = new TreeMap<String,String>();
map.put("aaaa", "month");
map.put("bbbb", "bread");
map.put("ccccc", "attack");
//通过ArrayList构造函数把map.entrySet()转换成list
mappingList = new ArrayList<Map.Entry<String,String>>(map.entrySet());
//通过比较器实现比较排序
Collections.sort(mappingList, new Comparator<Map.Entry<String,String>>(){
public int compare(Map.Entry<String,String> mapping1,Map.Entry<String,String> mapping2){
return mapping1.getValue().compareTo(mapping2.getValue());
}
});
for(Map.Entry<String,String> mapping:mappingList){
System.out.println(mapping.getKey()+":"+mapping.getValue());
}
eg.2 对HashMap(或Hashtable,LinkedHashMap)按照key的值升序:
List<Map.Entry<String,String>> mappingList = null;
Map<String,String> map = new HashMap<String,String>();
map.put("month", "month");
map.put("bread", "bread");
map.put("attack", "attack");
//通过ArrayList构造函数把map.entrySet()转换成list
mappingList = new ArrayList<Map.Entry<String,String>>(map.entrySet());
//通过比较器实现比较排序
Collections.sort(mappingList, new Comparator<Map.Entry<String,String>>(){
public int compare(Map.Entry<String,String> mapping1,Map.Entry<String,String> mapping2){
return mapping1.getKey().compareTo(mapping2.getKey());
}
});
for(Map.Entry<String,String> mapping:mappingList){
System.out.println(mapping.getKey()+":"+mapping.getValue());
}
二十、Java 中 BigDecimal 的相关用法
1.BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) 方法
BigDecimal b = new BigDecimal(“10.01”);
b.divide(1,2,4)
1 表示除以 1
2 表示2位小数
4 是BigDecimal.ROUND_HALF_UP,也就是最常见的四舍五入,大于一般则向上舍入,否则向下舍入
2. java中的BigDecimal和String的相互转换
//数字字符串
String StrBd="1048576.1024";
//构造以字符串内容为值的BigDecimal类型的变量bd
BigDecimal bd=new BigDecimal(StrBd);
//设置小数位数,第一个变量是小数位数,第二个变量是取舍方法(四舍五入)
bd=bd.setScale(2, BigDecimal.ROUND_HALF_UP);
//转化为字符串输出
String OutString=bd.toString();
3. java中的 BigDecimal加减乘除运算
package test1;
import java.math.BigDecimal;
/**
* 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精 确的浮点数运算,包括加减乘除和四舍五入。
*/
public class Arith { // 默认除法运算精度
private static final int DEF_DIV_SCALE = 10; // 这个类不能实例化
private Arith() {
}
/**
* 提供精确的加法运算。
*
* @param v1
* 被加数
* @param v2
* 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
*
* @param v1
* 被减数
* @param v2
* 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
*
* @param v1
* 被乘数
* @param v2
* 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @param scale
* 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
*
* @param v
* 需要四舍五入的数字
* @param scale
* 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
二十一、Java ,JSON 之间互相转换
jackson-databind-2.2.1.jar
jackson-annotations-2.2.1.jar
jackson-core-2.2.1.jar
jackson-mapper-asl-1.9.13.jar
jackson-core-asl-1.9.13.jar
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.JavaType;
public class JsonUtil {
private static ObjectMapper mapper = new ObjectMapper(); // can reuse, share
// globally
static {
mapper.configure(
DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
/**
* 把 java 对象转化为 json 对象
*/
public static <T> String java2json(T t) {
String json = null;
try {
json = mapper.writeValueAsString(t); // 把 java 对象转化为 json 对象
} catch (JsonGenerationException ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null,
ex);
} catch (JsonMappingException ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null,
ex);
} catch (IOException ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null,
ex);
}
return json;
}
/**
* 把 json 对象转化为 java 对象
*
*/
public static <T> T json2java(String json, Class<T> valueType) {
T obj = null;
try {
obj = mapper.readValue(json, valueType); // 把 json 对象转化为 java 对象
// User user = mapper.readValue(json, User.class); // 把 json 对象转化为
// java 对象
} catch (JsonGenerationException ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null,
ex);
} catch (JsonMappingException ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null,
ex);
} catch (IOException ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null,
ex);
}
return obj;
}
public static <T> List<T> json2javaList(String json, Class<T> valueType) {
List<T> obj = null;
try {
JavaType javaType = mapper.getTypeFactory()
.constructParametricType(ArrayList.class, valueType);
//解决不能反序列化
mapper.configure(
DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY,
true);
obj = mapper.readValue(json, javaType); // 把 json 对象转化为 java 对象
} catch (JsonGenerationException ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null,
ex);
} catch (JsonMappingException ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null,
ex);
} catch (IOException ex) {
Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null,
ex);
}
return obj;
}
/**
* 打印map
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void printMap(Map map) {
Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.println("key = " + key);
Object obj = map.get(key);
String className = obj.getClass().getName();
System.out.println("type =" + className);
boolean isMap = className.toLowerCase().indexOf("map") >= 0;
boolean isList = className.toLowerCase().indexOf("list") >= 0;
if (isMap) {
System.out.println("==== is map ====");
printMap((Map) obj); // 递归调用
} else if (isList) {
List list = (List) obj;
System.out.println("==== is list ==== , size = " + list.size());
for (Object oo : list) {
System.out.println("element type ="
+ oo.getClass().getName());
System.out.println("element toString =" + oo.toString());
}
} else {
System.out.println("obj.toString = " + obj.toString());
}
}
}
}
二十二、Arrays.asList() 的bug
常常使用Arrays.asLisvt()后调用add,remove这些method时出现java.lang.UnsupportedOperationException异常。这是由于:
Arrays.asList() 返回java.util.Arrays$ArrayList, 而不是ArrayList。Arrays$ArrayList和ArrayList都是继承AbstractList,remove,add等method在AbstractList中是默认throw UnsupportedOperationException而且不作任何操作。ArrayList override这些method来对list进行操作,但是Arrays$ArrayList没有override remove(int),add(int)等,所以throw UnsupportedOperationException。
解决方法是使用Iterator,或者转换为ArrayList
List list = Arrays.asList(a[]);
List arrayList = new ArrayList(list);